Learn AppleScript: The Comprehensive Guide To Scripting And Automation On Mac OS X, Third Edition Apple Script
User Manual:
Open the PDF directly: View PDF
.
Page Count: 1106
Table of Contents
Copyright................................................................................................................................ 1
Foreword.............................................................................................................................. 18
About the Authors................................................................................................................ 20
About the Technical Reviewer............................................................................................... 21
Acknowledgments................................................................................................................. 22
Introduction......................................................................................................................... 23
Part 1: Welcome to AppleScript............................................................................................ 28
Chapter 1. Introducing AppleScript.............................................................................................................................................................................................. 30
Section 1.1. Automating with AppleScript: From Small Tasks to Large................................................................................................................................... 30
Section 1.2. The Golden Triangle: Scriptable Applications, the AppleScript Language, and the Scripts You Write.............................................................. 33
Section 1.3. Your First AppleScript: Hello World!.................................................................................................................................................................... 37
Section 1.4. Summary................................................................................................................................................................................................................ 40
Chapter 2. AppleScript in Principle.............................................................................................................................................................................................. 42
Section 2.1. The Four Key Concepts of Application Scripting.................................................................................................................................................. 43
Section 2.2. The Four Key Concepts of the AppleScript Language.......................................................................................................................................... 49
Section 2.3. Tying It All Together: What Makes AppleScript Special....................................................................................................................................... 55
Section 2.4. Summary................................................................................................................................................................................................................ 58
Chapter 3. AppleScript in Practice................................................................................................................................................................................................ 60
Section 3.1. The Project: Tidy Desktop..................................................................................................................................................................................... 60
Section 3.2. Planning the Script................................................................................................................................................................................................. 61
Section 3.3. Writing the Script.................................................................................................................................................................................................. 62
Section 3.4. Final Thoughts....................................................................................................................................................................................................... 73
Section 3.5. Summary................................................................................................................................................................................................................ 76
Part 2: Understanding AppleScript....................................................................................... 78
Chapter 4. Writing Scripts in AppleScript Editor........................................................................................................................................................................ 80
Section 4.1. Working with Script Windows.............................................................................................................................................................................. 80
Section 4.2. Viewing Application Dictionaries.......................................................................................................................................................................... 84
Section 4.3. Other Useful AppleScript Editor Features............................................................................................................................................................ 85
Section 4.4. Saving Scripts........................................................................................................................................................................................................ 92
Section 4.5. Other Tools for Writing and Running AppleScripts............................................................................................................................................. 99
Section 4.6. Summary.............................................................................................................................................................................................................. 103
Chapter 5. Understanding How Application Scripting Works................................................................................................................................................... 104
Section 5.1. A Quick Application Scripting Example............................................................................................................................................................... 105
Section 5.2. Understanding Objects........................................................................................................................................................................................ 106
Section 5.3. Understanding Commands................................................................................................................................................................................... 113
Section 5.4. Understanding the Application Object Model..................................................................................................................................................... 118
Section 5.5. Understanding Application Dictionaries............................................................................................................................................................. 130
Section 5.6. More on application Objects................................................................................................................................................................................ 150
Section 5.7. More on Constructing References........................................................................................................................................................................ 155
Section 5.8. Summary.............................................................................................................................................................................................................. 166
Chapter 6. Learning to Work with AppleScript Objects............................................................................................................................................................. 170
Section 6.1. How AppleScript Represents Information As Objects......................................................................................................................................... 171
Section 6.2. How AppleScript Works with Objects................................................................................................................................................................. 173
Section 6.3. Working with Boolean Objects............................................................................................................................................................................ 184
Section 6.4. Summary.............................................................................................................................................................................................................. 188
Chapter 7. Working with Text..................................................................................................................................................................................................... 190
Section 7.1. Introducing Text................................................................................................................................................................................................... 190
Section 7.2. How to Write Literal Strings in AppleScript........................................................................................................................................................ 197
Section 7.3. The Properties of Text.......................................................................................................................................................................................... 201
Section 7.4. The Elements of Text........................................................................................................................................................................................... 202
Section 7.5. Operators and Commands.................................................................................................................................................................................. 208
Section 7.6. Working with Text Item Delimiters..................................................................................................................................................................... 219
Section 7.7. How AppleScript Text Works in Tiger................................................................................................................................................................. 224
Section 7.8. Example Projects................................................................................................................................................................................................. 228
Section 7.9. Summary.............................................................................................................................................................................................................. 240
Chapter 8. Working with Numbers............................................................................................................................................................................................. 242
Section 8.1. Introducing Integers and Reals........................................................................................................................................................................... 242
Section 8.2. Operators and Commands.................................................................................................................................................................................. 243
Section 8.3. Example Projects................................................................................................................................................................................................. 258
Section 8.4. Summary.............................................................................................................................................................................................................. 267
Chapter 9. Working with Dates................................................................................................................................................................................................... 268
Section 9.1. Introducing Dates................................................................................................................................................................................................ 268
Section 9.2. The Properties of Dates....................................................................................................................................................................................... 274
Section 9.3. Operators and Commands................................................................................................................................................................................... 279
Section 9.4. Example Projects................................................................................................................................................................................................. 285
Section 9.5. Summary.............................................................................................................................................................................................................. 293
Chapter 10. Working with Lists and Records............................................................................................................................................................................. 294
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
Section 10.1. Introducing Lists and Records........................................................................................................................................................................... 294
Section 10.2. Working with Lists............................................................................................................................................................................................. 296
Section 10.3. Working with Records....................................................................................................................................................................................... 309
Section 10.4. Example Project: Measuring Word Frequency in TextEdit.............................................................................................................................. 314
Section 10.5. Summary............................................................................................................................................................................................................. 319
Chapter 11. Storing Objects in Variables..................................................................................................................................................................................... 320
Section 11.1. Creating Variables............................................................................................................................................................................................... 320
Section 11.2. Working with Local Variables............................................................................................................................................................................ 326
Section 11.3. Working with Properties and Global Variables................................................................................................................................................. 332
Section 11.4. Using AppleScript's Built-in Variables............................................................................................................................................................... 337
Section 11.5. Summary............................................................................................................................................................................................................. 345
Chapter 12. More on Commands................................................................................................................................................................................................ 346
Section 12.1. Understanding How and Where Commands Are Defined................................................................................................................................ 346
Section 12.2. Picking the Right Target for Your Commands.................................................................................................................................................. 352
Section 12.3. The Five Standard AppleScript Commands...................................................................................................................................................... 354
Section 12.4. Commands That All Applications Understand................................................................................................................................................. 358
Section 12.5. The Standard Suite of Application Commands.................................................................................................................................................. 361
Section 12.6. More on Working with get, set, and copy Commands...................................................................................................................................... 372
Section 12.7. Changing How Commands Are Handled........................................................................................................................................................... 381
Section 12.8. Sending Commands to Remote Applications.................................................................................................................................................... 386
Section 12.9. Summary............................................................................................................................................................................................................ 393
Chapter 13. More on Operators and Coercions.......................................................................................................................................................................... 396
Section 13.1. Understanding the a reference to Operator....................................................................................................................................................... 396
Section 13.2. Introducing Unit Type Conversions.................................................................................................................................................................. 400
Section 13.3. A Summary of AppleScript Coercions................................................................................................................................................................ 401
Section 13.4. A Summary of AppleScript Operators............................................................................................................................................................... 406
Section 13.5. Operator Precedence in Detail............................................................................................................................................................................ 411
Section 13.6. Summary............................................................................................................................................................................................................. 415
Chapter 14. Making Decisions Using Conditionals and Loops................................................................................................................................................... 416
Section 14.1. Choosing Your Course with Conditional Blocks................................................................................................................................................. 416
Section 14.2. Running an Assembly Line with Repeat Loops................................................................................................................................................. 421
Section 14.3. Summary............................................................................................................................................................................................................ 437
Chapter 15. Making Decisions When Dealing with Errors......................................................................................................................................................... 440
Section 15.1. Understanding Compilation Errors.................................................................................................................................................................... 441
Section 15.2. Understanding Runtime Errors......................................................................................................................................................................... 443
Section 15.3. Understanding Common Error Numbers......................................................................................................................................................... 458
Section 15.4. Summary............................................................................................................................................................................................................ 462
Chapter 16. Interacting with the User......................................................................................................................................................................................... 464
Section 16.1. Creating Basic Dialog Boxes and Gathering Text Input.................................................................................................................................... 464
Section 16.2. Choosing Files, Folders, and Disks.................................................................................................................................................................... 481
Section 16.3. Choosing Other Types of Items......................................................................................................................................................................... 492
Section 16.4. Summary............................................................................................................................................................................................................ 497
Chapter 17. Working with Files................................................................................................................................................................................................... 498
Section 17.1. Identifying Files, Folders, and Disks.................................................................................................................................................................. 498
Section 17.2. Reading and Writing Files.................................................................................................................................................................................. 510
Section 17.3. Summary............................................................................................................................................................................................................ 529
Chapter 18. Organizing Your Code with Handlers..................................................................................................................................................................... 532
Section 18.1. What Are User-Defined Handlers?.................................................................................................................................................................... 532
Section 18.2. Creating a Simple Handler................................................................................................................................................................................ 534
Section 18.3. Using Parameters............................................................................................................................................................................................... 535
Section 18.4. What's the Result?............................................................................................................................................................................................. 536
Section 18.5. Specifying Handler Parameters......................................................................................................................................................................... 539
Section 18.6. Introducing Recursion....................................................................................................................................................................................... 546
Section 18.7. Using the run Handler in Scripts....................................................................................................................................................................... 547
Section 18.8. Working with Handlers in Applets.................................................................................................................................................................... 549
Section 18.9. Tips for Designing and Using Handlers............................................................................................................................................................ 553
Section 18.10. Example Project: A Reusable Associative List................................................................................................................................................. 556
Section 18.11. Summary........................................................................................................................................................................................................... 565
Chapter 19. Organizing Your Code with Script Objects.............................................................................................................................................................. 568
Section 19.1. Introducing Script Objects................................................................................................................................................................................. 568
Section 19.2. Understanding Script Objects............................................................................................................................................................................ 570
Section 19.3. Working with Script Libraries............................................................................................................................................................................ 575
Section 19.4. Beginning Object-Oriented Programming........................................................................................................................................................ 583
Section 19.5. Summary............................................................................................................................................................................................................ 610
Part 3: Putting AppleScript to Work.................................................................................... 612
Chapter 20. Scripting the File System......................................................................................................................................................................................... 614
Section 20.1. How the Finder Represents the Mac OS X File System.................................................................................................................................... 614
Section 20.2. How System Events Represents the Mac OS X File System............................................................................................................................. 622
Section 20.3. Working with Finder Items............................................................................................................................................................................... 629
Section 20.4. More on Working with Folders......................................................................................................................................................................... 637
Section 20.5. Locating Important Files and Folders with Standard Additions..................................................................................................................... 639
Section 20.6. Mounting Volumes............................................................................................................................................................................................ 645
Section 20.7. Summary........................................................................................................................................................................................................... 648
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
Chapter 21. Scripting Apple Applications................................................................................................................................................................................... 650
Section 21.1. Scripting iTunes.................................................................................................................................................................................................. 650
Section 21.2. Scripting Mail..................................................................................................................................................................................................... 662
Section 21.3. Scripting iCal...................................................................................................................................................................................................... 677
Section 21.4. Scripting Address Book..................................................................................................................................................................................... 682
Section 21.5. Scripting Automator.......................................................................................................................................................................................... 693
Section 21.6. Summary............................................................................................................................................................................................................ 700
Chapter 22. Extending AppleScript with Scripting Additions................................................................................................................................................... 702
Section 22.1. Introducing Scripting Additions and Scriptable Faceless Background Applications...................................................................................... 702
Section 22.2. Scripting Additions in Detail............................................................................................................................................................................. 704
Section 22.3. Understanding Scriptable Faceless Background Applications.......................................................................................................................... 715
Section 22.4. Examples of AppleScript Extensions................................................................................................................................................................. 716
Section 22.5. Using the Standard Additions Scripting Addition............................................................................................................................................. 717
Section 22.6. Using the Image Events Faceless Background Application.............................................................................................................................. 722
Section 22.7. Processing Text with the Satimage Scripting Addition..................................................................................................................................... 724
Section 22.8. Summary............................................................................................................................................................................................................ 737
Chapter 23. AppleScript Amenities............................................................................................................................................................................................. 738
Section 23.1. Using the Services Menu.................................................................................................................................................................................... 738
Section 23.2. Scheduling Scripts with iCal.............................................................................................................................................................................. 742
Section 23.3. Triggering Scripts with Folder Actions............................................................................................................................................................. 743
Section 23.4. Controlling Applications with GUI Scripting.................................................................................................................................................... 749
Section 23.5. Working with the Clipboard.............................................................................................................................................................................. 763
Section 23.6. Summary............................................................................................................................................................................................................ 769
Chapter 24. Scripting iWork and Office...................................................................................................................................................................................... 770
Section 24.1. Scripting iWork.................................................................................................................................................................................................. 770
Section 24.2. Scripting Microsoft Office.................................................................................................................................................................................. 787
Section 24.3. Summary............................................................................................................................................................................................................ 819
Chapter 25. Scripting Data and Databases................................................................................................................................................................................. 820
Section 25.1. Automating FileMaker Pro with AppleScript.................................................................................................................................................... 821
Section 25.2. Scripting Runtime Labs' MacSQL..................................................................................................................................................................... 834
Section 25.3. Database Events................................................................................................................................................................................................ 839
Section 25.4. Summary............................................................................................................................................................................................................ 841
Chapter 26. Scripting Adobe InDesign....................................................................................................................................................................................... 844
Section 26.1. Learning by Example......................................................................................................................................................................................... 845
Section 26.2. Understanding the InDesign Object Model...................................................................................................................................................... 847
Section 26.3. Working with Documents................................................................................................................................................................................. 852
Section 26.4. Working with Text............................................................................................................................................................................................. 858
Section 26.5. Working with Graphics..................................................................................................................................................................................... 862
Section 26.6. Drawing Lines.................................................................................................................................................................................................... 863
Section 26.7. Example Project: An InDesign Scripts Launcher............................................................................................................................................. 864
Section 26.8. Working with Tables......................................................................................................................................................................................... 867
Section 26.9. Working with Selections.................................................................................................................................................................................... 872
Section 26.10. Labeling Objects for Use in Workflow Scripts................................................................................................................................................ 877
Section 26.11. Taking Advantage of AppleScript-Specific Preferences.................................................................................................................................. 879
Section 26.12. Example Project: Replacing Tags with Images............................................................................................................................................... 881
Section 26.13. Using InDesign on a Server............................................................................................................................................................................. 888
Section 26.14. Summary.......................................................................................................................................................................................................... 888
Chapter 27. Interacting with the Unix Command Line.............................................................................................................................................................. 890
Section 27.1. Why and When Are Shell Scripts Used in AppleScript?................................................................................................................................... 890
Section 27.2. Understanding Unix Scripting Concepts........................................................................................................................................................... 891
Section 27.3. Running Shell Scripts from AppleScript........................................................................................................................................................... 900
Section 27.4. Running AppleScript from Shell Scripts............................................................................................................................................................ 913
Section 27.5. Example Projects................................................................................................................................................................................................ 915
Section 27.6. Summary............................................................................................................................................................................................................ 923
Chapter 28. Using Smile: The AppleScript Integrated Production Environment..................................................................................................................... 924
Section 28.1. Introducing Smile.............................................................................................................................................................................................. 924
Section 28.2. Downloading Smile........................................................................................................................................................................................... 926
Section 28.3. Using Smile........................................................................................................................................................................................................ 926
Section 28.4. Example Project: Adding Text to a PDF Document......................................................................................................................................... 935
Section 28.5. Summary............................................................................................................................................................................................................ 953
Chapter 29. Tips and Techniques for Improving Your Scripts................................................................................................................................................... 954
Section 29.1. Design, in a Nutshell.......................................................................................................................................................................................... 955
Section 29.2. Testing and Debugging Your Code.................................................................................................................................................................... 961
Section 29.3. Improving the Performance of Your Code........................................................................................................................................................ 975
Section 29.4. Summary............................................................................................................................................................................................................ 993
Chapter 30. Creating Cocoa Applications with AppleScriptObjC.............................................................................................................................................. 996
Section 30.1. Example Project: HelloAppleScriptObjC.......................................................................................................................................................... 997
Section 30.2. Understanding How Cocoa Works.................................................................................................................................................................. 1007
Section 30.3. Modifying HelloAppleScriptObjC to Set the Text Field.................................................................................................................................. 1010
Section 30.4. Example Project: PlaySound............................................................................................................................................................................ 1012
Section 30.5. Viewing the Cocoa Documentation in Xcode.................................................................................................................................................. 1017
Section 30.6. Example Project: SnapShot............................................................................................................................................................................. 1023
Section 30.7. Modifying SnapShot to Use Cocoa Bindings................................................................................................................................................... 1028
Section 30.8. Modifying PlaySound to Use Bundled Sound Files........................................................................................................................................ 1033
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
Section 30.9. Example Project: KitchenTimer...................................................................................................................................................................... 1036
Section 30.10. Extra Exercises............................................................................................................................................................................................... 1042
Section 30.11. Where Next?................................................................................................................................................................................................... 1043
Section 30.12. Summary........................................................................................................................................................................................................ 1044
Section 30.13. Conclusion...................................................................................................................................................................................................... 1045
bvdindexIndex.................................................................................................................. 1046
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X,
Third Edition
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal
All rights reserved. No part of this work may be reproduced or transmitted in any form or by
any means, electronic or mechanical, including photocopying, recording, or by any
information storage or retrieval system, without the prior written permission of the
copyright owner and the publisher.
ISBN-13 (pbk): 978-1-4302-2361-0
ISBN-13 (electronic): 978-1-4302-2362-7
Printed and bound in the United States of America 9 8 7 6 5 4 3 2 1
Trademarked names may appear in this book. Rather than use a trademark symbol with
every occurrence of a trademarked name, we use the names only in an editorial fashion and
to the benefit of the trademark owner, with no intention of infringement of the trademark.
Publisher and President: Paul Manning
Lead Editor: Douglas Pundick
Technical Reviewer: David A. Coyle
Editorial Board: Clay Andres, Steve Anglin, Mark Beckner, Ewan Buckingham, Gary
Cornell, Jonathan Gennick, Jonathan Hassell, Michelle Lowman, Matthew Moodie,
Duncan Parkes, Jeffrey Pepper, Frank Pohlmann, Douglas Pundick, Ben RenowClarke, Dominic Shakeshaft, Matt Wade, Tom Welsh
Coordinating Editor: Debra Kelly
Copy Editor: Bill McManus
Compositor: MacPS, LLC.
Indexer: BIM Indexing & Proofreading Services
Artist: April Milne
Cover Designer: Anna Ishchenko
Distributed to the book trade worldwide by Springer-Verlag New York, Inc., 233 Spring
Street, 6th Floor, New York, NY 10013. Phone 1-800-SPRINGER, fax 201-348-4505, e-mail
orders-ny@springer-sbm.com, or visit www.springeronline.com.
For information on translations, please e-mail rights@apress.com, or visit www.apress.com.
Apress and friends of ED books may be purchased in bulk for academic, corporate, or
promotional use. eBook versions and licenses are also available for most titles. For more
information, reference our Special Bulk Sales–eBook Licensing web page at
www.apress.com/info/bulksales.
The information in this book is distributed on an “as is” basis, without warranty. Although
every precaution has been taken in the preparation of this work, neither the author(s) nor
Apress shall have any liability to any person or entity with respect to any loss or damage
caused or alleged to be caused directly or indirectly by the information contained in this work.
The source code for this book is available to readers at www.apress.com.
ii
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
Contents at a Glance
Licensed by
Jim Kilcullen
2884260
■Contents at a Glance................................................................................................................ iii
■Contents.....................................................................................................................................v
■Foreword ................................................................................................................................xix
■About the Authors...................................................................................................................xxi
■About the Technical Reviewer ...............................................................................................xxii
■Acknowledgments ................................................................................................................xxiii
■Introduction .......................................................................................................................... xxiv
Part I: Welcome to AppleScript.................................................................................................... 1
■Chapter 1: Introducing AppleScript .......................................................................................... 3
■Chapter 2: AppleScript in Principle ........................................................................................ 15
■Chapter 3: AppleScript in Practice ......................................................................................... 33
Part II: Understanding AppleScript ............................................................................................ 51
■Chapter 4: Writing Scripts in AppleScript Editor .................................................................... 53
■Chapter 5: Understanding How Application Scripting Works ................................................. 77
■Chapter 6: Learning to Work with AppleScript Objects ........................................................ 143
■Chapter 7: Working with Text ............................................................................................... 163
■Chapter 8: Working with Numbers ....................................................................................... 215
■Chapter 9: Working with Dates............................................................................................. 241
■Chapter 10: Working with Lists and Records ....................................................................... 267
■Chapter 11: Storing Objects in Variables.............................................................................. 293
■Chapter 12: More on Commands .......................................................................................... 319
■Chapter 13: More on Operators and Coercions..................................................................... 369
■Chapter 14: Making Decisions Using Conditionals and Loops.............................................. 389
■Chapter 15: Making Decisions When Dealing with Errors .................................................... 413
■Chapter 16: Interacting with the User .................................................................................. 437
■Chapter 17: Working with Files ............................................................................................ 471
iii
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ CONTENTS AT A GLANCE
■Chapter 18: Organizing Your Code with Handlers ................................................................ 505
■Chapter 19: Organizing Your Code with Script Objects ........................................................ 541
Part III: Putting AppleScript to Work ....................................................................................... 585
■Chapter 20: Scripting the File System .................................................................................. 587
■Chapter 21: Scripting Apple Applications............................................................................. 623
■Chapter 22: Extending AppleScript with Scripting Additions ............................................... 675
■Chapter 23: AppleScript Amenities....................................................................................... 711
■Chapter 24: Scripting iWork and Office ................................................................................ 743
■Chapter 25: Scripting Data and Databases........................................................................... 793
■Chapter 26: Scripting Adobe InDesign.................................................................................. 817
■Chapter 27: Interacting with the Unix Command Line .......................................................... 863
■Chapter 28: Using Smile: The AppleScript Integrated
Production Environment ................................................................................................. 897
■Chapter 29: Tips and Techniques for Improving Your Scripts .............................................. 927
■Chapter 30: Creating Cocoa Applications with AppleScriptObjC .......................................... 969
■Index................................................................................................................................... 1019
iv
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
Contents
■Contents at a Glance................................................................................................................ iii
■Contents.....................................................................................................................................v
■Foreword ................................................................................................................................xix
■About the Authors...................................................................................................................xxi
■About the Technical Reviewer ...............................................................................................xxii
■Acknowledgments ................................................................................................................xxiii
■Introduction .......................................................................................................................... xxiv
Part I: Welcome to AppleScript.................................................................................................... 1
■Chapter 1: Introducing AppleScript .......................................................................................... 3
Automating with AppleScript: From Small Tasks to Large .....................................................................................3
Automating Small Tasks ....................................................................................................................................3
Automating Large Tasks ....................................................................................................................................4
When to Automate (or Not)?...............................................................................................................................5
The Golden Triangle: Scriptable Applications, the AppleScript Language, and the Scripts You Write ...................6
What Is a Scriptable Application? ......................................................................................................................6
What Is the AppleScript Language?...................................................................................................................8
What Is a Script?................................................................................................................................................9
Your First AppleScript: Hello World!......................................................................................................................10
Summary ..............................................................................................................................................................13
■Chapter 2: AppleScript in Principle ........................................................................................ 15
The Four Key Concepts of Application Scripting...................................................................................................16
How Applications Represent Information As Objects.......................................................................................16
How Applications Manipulate Objects Using Commands ................................................................................18
How Applications Organize Their Objects into Object Models .........................................................................19
How Applications Describe Their Objects and Commands in Dictionaries ......................................................21
The Four Key Concepts of the AppleScript Language...........................................................................................22
How AppleScript Represents Information As Objects ......................................................................................23
How AppleScript Manipulates Objects Using Commands, Operators, and Variables ......................................24
How AppleScript Organizes Code Using Handlers and Script Objects .............................................................26
v
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ CONTENTS
Tying It All Together: What Makes AppleScript Special ........................................................................................28
The English-like Syntax ...................................................................................................................................28
Built-in Application Scripting Support .............................................................................................................29
Attaching Scripts to Applications.....................................................................................................................29
The AppleScript Community ............................................................................................................................30
Summary ..............................................................................................................................................................31
■Chapter 3: AppleScript in Practice ......................................................................................... 33
The Project: Tidy Desktop .....................................................................................................................................33
Planning the Script ...............................................................................................................................................34
Writing the Script..................................................................................................................................................35
Creating the Folder Name ................................................................................................................................35
Interacting with the File System ......................................................................................................................39
Final Thoughts ......................................................................................................................................................46
Improving Reliability ........................................................................................................................................46
Adding Features...............................................................................................................................................47
Documenting Your Code ..................................................................................................................................48
Summary ..............................................................................................................................................................49
Part II: Understanding AppleScript ............................................................................................ 51
■Chapter 4: Writing Scripts in AppleScript Editor .................................................................... 53
Working with Script Windows...............................................................................................................................53
Compiling a Script............................................................................................................................................54
Running and Stopping a Script ........................................................................................................................55
Recording a Script ...........................................................................................................................................55
Viewing the Result of Running a Script ...........................................................................................................56
Viewing the Events Sent by a Running Script..................................................................................................56
Adding a Description to a Script ......................................................................................................................57
Viewing Application Dictionaries ..........................................................................................................................57
Other Useful AppleScript Editor Features .............................................................................................................58
Using the Library Window................................................................................................................................59
Navigating to a Handler in a Script ..................................................................................................................60
Viewing the Event Log History .........................................................................................................................61
Scripting the AppleScript Editor.......................................................................................................................61
Using Context Menu Scripts.............................................................................................................................62
Viewing the Bundle Contents Drawer ..............................................................................................................62
Setting the Script Formatting Preferences ......................................................................................................63
Saving Scripts.......................................................................................................................................................65
Text-Based Scripts...........................................................................................................................................66
Compiled Scripts..............................................................................................................................................66
Script-Based Applications (Applets) ................................................................................................................69
Other Tools for Writing and Running AppleScripts ...............................................................................................72
The System-wide Script Menu.........................................................................................................................72
Third-Party AppleScript Editors .......................................................................................................................74
Developing GUI Applications ............................................................................................................................76
Command-Line Tools .......................................................................................................................................76
Summary ..............................................................................................................................................................76
■Chapter 5: Understanding How Application Scripting Works ................................................. 77
A Quick Application Scripting Example.................................................................................................................78
Understanding Objects..........................................................................................................................................79
How Objects Are Categorized by Class ............................................................................................................79
Introducing Object Properties ..........................................................................................................................81
vi
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ CONTENTS
Introducing Object Elements............................................................................................................................84
Understanding Commands....................................................................................................................................86
Introducing Command Names .........................................................................................................................87
Introducing Command Parameters ..................................................................................................................87
Commands Must Be Targeted at Objects.........................................................................................................89
Commands Can Return Results or Report Errors.............................................................................................90
Understanding the Application Object Model........................................................................................................91
How Objects Can Contain Other Objects..........................................................................................................92
How AppleScript Refers to Application Objects ...............................................................................................93
Exploring a Typical Object Model.....................................................................................................................98
Understanding Application Dictionaries..............................................................................................................103
Introducing AppleScript Editor’s Dictionary Viewer .......................................................................................104
How Classes Are Documented.......................................................................................................................107
How Commands Are Documented .................................................................................................................118
Application Dictionaries Don’t Tell You Everything! .......................................................................................120
More on application Objects ...............................................................................................................................123
Creating application Objects..........................................................................................................................123
The Standard Properties of application Objects ............................................................................................126
How AppleScript Compiles tell application ... Blocks ....................................................................................127
More on Constructing References ......................................................................................................................128
Referring to Properties...................................................................................................................................129
Referring to Elements ....................................................................................................................................129
Referring to Insertion Locations.....................................................................................................................138
Summary ............................................................................................................................................................139
■Chapter 6: Learning to Work with AppleScript Objects ........................................................ 143
How AppleScript Represents Information As Objects .........................................................................................144
What Kinds of Objects Does AppleScript Provide? ........................................................................................144
Creating New Objects ....................................................................................................................................145
Getting Information from Objects...................................................................................................................145
How AppleScript Works with Objects .................................................................................................................146
Manipulating Objects with Commands ..........................................................................................................146
Manipulating Objects with Operators ............................................................................................................148
Coercing Objects............................................................................................................................................153
Storing Objects in Variables...........................................................................................................................154
Working with Boolean Objects............................................................................................................................157
Boolean Operators .........................................................................................................................................158
Boolean-Related Coercions............................................................................................................................160
Summary ............................................................................................................................................................161
■Chapter 7: Working with Text ............................................................................................... 163
Introducing Text ..................................................................................................................................................163
A Brief History of Text ....................................................................................................................................164
Introducing Text in AppleScript 2.0................................................................................................................169
How to Write Literal Strings in AppleScript ........................................................................................................170
The Properties of Text.........................................................................................................................................174
The class Property .......................................................................................................................................174
The length Property .....................................................................................................................................174
The quoted form Property...........................................................................................................................174
The id Property .............................................................................................................................................174
The Elements of Text ..........................................................................................................................................175
Characters .....................................................................................................................................................175
vii
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ CONTENTS
Words.............................................................................................................................................................178
Paragraphs.....................................................................................................................................................179
Text Ranges ...................................................................................................................................................179
Operators and Commands ..................................................................................................................................181
Joining Strings...............................................................................................................................................181
Comparing Strings .........................................................................................................................................182
Checking for Strings Within Strings...............................................................................................................184
Considering and Ignoring Attributes ..............................................................................................................185
The count Command......................................................................................................................................189
The offset Command......................................................................................................................................189
Coercing to and from Text .............................................................................................................................190
Working with Text Item Delimiters......................................................................................................................192
Splitting Strings with Text Item Delimiters ....................................................................................................192
Combining List Items into a Single String......................................................................................................194
Finding and Replacing Text ...........................................................................................................................196
How AppleScript Text Works in Tiger .................................................................................................................197
The Many Different Classes of Text ...............................................................................................................198
Working with the Various Text Classes..........................................................................................................198
The ASCII number and ASCII character Commands.......................................................................................200
Example Projects ................................................................................................................................................201
Defining a Find-and-Replace Command........................................................................................................202
Transferring Meeting Arrangements from Mail to iCal ..................................................................................204
Summary ............................................................................................................................................................213
■Chapter 8: Working with Numbers ....................................................................................... 215
Introducing Integers and Reals ...........................................................................................................................215
Operators and Commands ..................................................................................................................................216
Math Operations ............................................................................................................................................217
Comparison Operations .................................................................................................................................221
Introducing Operator Precedence ..................................................................................................................224
The round Command......................................................................................................................................225
The random number Command .....................................................................................................................227
Coercing to and from Numbers......................................................................................................................229
Example Projects ................................................................................................................................................231
Defining a Round-to-Decimal-Places Command ...........................................................................................231
Blackjack! ......................................................................................................................................................233
Kitchen Timer.................................................................................................................................................237
Summary ............................................................................................................................................................240
■Chapter 9: Working with Dates............................................................................................. 241
Introducing Dates................................................................................................................................................241
Understanding Date and Time Formats .........................................................................................................242
Forming Dates On-the-Fly..............................................................................................................................244
Specifying a Time Relative to a Date .............................................................................................................246
The Properties of Dates ......................................................................................................................................247
The class Property .......................................................................................................................................247
The year Property .........................................................................................................................................247
The month Property .......................................................................................................................................247
The day Property ...........................................................................................................................................248
The weekday Property...................................................................................................................................248
The hours Property .......................................................................................................................................249
The minutes Property...................................................................................................................................249
viii
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ CONTENTS
The seconds Property...................................................................................................................................249
The time Property .........................................................................................................................................249
The date string Property...........................................................................................................................250
The short date string Property ..............................................................................................................250
The time string Property...........................................................................................................................250
Setting Date Properties..................................................................................................................................250
Operators and Commands ..................................................................................................................................252
Comparison Operators ...................................................................................................................................252
Math Operators ..............................................................................................................................................254
The current date Command......................................................................................................................257
The time to GMT Command........................................................................................................................258
Example Projects ................................................................................................................................................258
Deleting Old Files...........................................................................................................................................259
Alarm Clock....................................................................................................................................................263
Summary ............................................................................................................................................................266
■Chapter 10: Working with Lists and Records ....................................................................... 267
Introducing Lists and Records ............................................................................................................................267
What Is a List? ...............................................................................................................................................267
What Is a Record?..........................................................................................................................................268
How Are Lists and Records Used in Scripts?.................................................................................................269
Working with Lists ..............................................................................................................................................269
The Properties of a List..................................................................................................................................270
The Elements of a List ...................................................................................................................................271
Operators and Commands .............................................................................................................................274
Processing List Items with a Repeat Loop.....................................................................................................279
Sorting Items in a List....................................................................................................................................281
Working with Records.........................................................................................................................................282
Getting and Setting the Properties of a Record .............................................................................................284
Operators and Commands .............................................................................................................................286
Example Project: Measuring Word Frequency in TextEdit ..................................................................................287
Planning the Script ........................................................................................................................................287
Developing the Script.....................................................................................................................................288
Conclusion .....................................................................................................................................................291
Summary ............................................................................................................................................................292
■Chapter 11: Storing Objects in Variables.............................................................................. 293
Creating Variables...............................................................................................................................................293
Declaring Your Variables................................................................................................................................294
Choosing Your Variable Names......................................................................................................................295
Working with Local Variables .............................................................................................................................299
Understanding Local Variable Scope .............................................................................................................300
Passing Values to and from User-Defined Handlers ......................................................................................303
Working with Properties and Global Variables....................................................................................................305
Understanding Property and Global Variable Scope ......................................................................................305
How Properties (and Global Variables) Can Retain Values Between Runs.....................................................306
When to Use Properties and Global Variables................................................................................................307
Using AppleScript’s Built-in Variables ................................................................................................................310
Variables Containing Predefined Values ........................................................................................................311
Variables Containing Objects of Special Interest ...........................................................................................313
Summary ............................................................................................................................................................318
■Chapter 12: More on Commands .......................................................................................... 319
ix
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ CONTENTS
Understanding How and Where Commands Are Defined....................................................................................319
Application-Defined Commands ....................................................................................................................319
Scripting Addition Commands .......................................................................................................................322
AppleScript Commands .................................................................................................................................323
User-Defined Commands...............................................................................................................................324
Picking the Right Target for Your Commands.....................................................................................................325
The Five Standard AppleScript Commands ........................................................................................................327
The get Command..........................................................................................................................................327
The set Command..........................................................................................................................................327
The copy Command .......................................................................................................................................328
The count Command......................................................................................................................................330
The run Command .........................................................................................................................................330
Commands That All Applications Understand.....................................................................................................331
The run Command .........................................................................................................................................331
The launch Command ....................................................................................................................................332
The open Command.......................................................................................................................................332
The activate Command ..................................................................................................................................333
The quit Command.........................................................................................................................................333
The Standard Suite of Application Commands ...................................................................................................334
The get Command..........................................................................................................................................334
The set Command..........................................................................................................................................335
The make Command......................................................................................................................................336
The exists Command .....................................................................................................................................338
The count Command......................................................................................................................................338
The move Command ......................................................................................................................................339
The duplicate Command ................................................................................................................................340
The delete Command.....................................................................................................................................341
The print Command .......................................................................................................................................342
The save Command .......................................................................................................................................343
The close Command ......................................................................................................................................344
More on Working with get, set, and copy Commands ........................................................................................345
When Do Implicit get Commands Occur? ......................................................................................................345
When Are Explicit get Commands Necessary? ..............................................................................................347
Telling the Difference Between AppleScript and Application set Commands................................................350
Getting and Setting Multiple Values in a Single Statement ...........................................................................351
Using copy As an Application Command .......................................................................................................352
Changing How Commands Are Handled .............................................................................................................354
Considering and Ignoring Application Responses..........................................................................................354
Considering and Ignoring Other Attributes.....................................................................................................357
Controlling the Timeout Delay for Long-Running Commands........................................................................357
Sending Commands to Remote Applications......................................................................................................359
Enabling Remote Apple Events ......................................................................................................................359
Talking to Remote Machines .........................................................................................................................361
Authenticating Access to Remote Machines .................................................................................................362
Compiling Scripts Offline ...............................................................................................................................363
Using the choose remote application Command ...........................................................................................364
Targeting Remote Applications by User and Process IDs ..............................................................................364
Launching Remote Applications ....................................................................................................................366
Summary ............................................................................................................................................................366
■Chapter 13: More on Operators and Coercions..................................................................... 369
Understanding the a reference to Operator ........................................................................................................369
x
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ CONTENTS
Introducing Unit Type Conversions .....................................................................................................................373
A Summary of AppleScript Coercions .................................................................................................................374
Coercing Class and Constant Names .............................................................................................................375
Coercing Numbers and Text ..........................................................................................................................376
Coercing File Objects .....................................................................................................................................377
Coercing Lists ................................................................................................................................................378
A Summary of AppleScript Operators .................................................................................................................379
Boolean Logic Operators................................................................................................................................379
The Concatenation Operator ..........................................................................................................................379
Math Operators ..............................................................................................................................................380
Comparison Operators ...................................................................................................................................381
Containment Operators..................................................................................................................................382
The Coercion Operator ...................................................................................................................................383
The a reference to Operator...........................................................................................................................383
Operator Precedence in Detail ............................................................................................................................384
Understanding Precedence............................................................................................................................385
Understanding Forms of Association .............................................................................................................386
Understanding when You Should Use Parentheses .......................................................................................387
Summary ............................................................................................................................................................388
Licensed by
Jim Kilcullen
2884260
■Chapter 14: Making Decisions Using Conditionals and Loops.............................................. 389
Choosing Your Course with Conditional Blocks ..................................................................................................389
Understanding the Basic Conditional Statement ...........................................................................................390
The Different Flavors of Conditional Statements ...........................................................................................391
Offering an Alternative Ending with the else Clause......................................................................................391
Offering Multiple Choices with else if Clauses ..............................................................................................392
Tips for Writing Conditional Statements ........................................................................................................393
Running an Assembly Line with Repeat Loops ...................................................................................................394
The Different Flavors of Repeat Loops...........................................................................................................395
Repeating Forever..........................................................................................................................................396
Repeating n Times .........................................................................................................................................397
Repeating with Numbers in a Range .............................................................................................................397
Repeating with Items in a List .......................................................................................................................400
Repeating While/Until a Condition Is Met.......................................................................................................404
Tips for Writing Repeat Statements...............................................................................................................406
Summary ............................................................................................................................................................410
■Chapter 15: Making Decisions When Dealing with Errors .................................................... 413
Understanding Compilation Errors......................................................................................................................414
Simple Typos .................................................................................................................................................414
Unbalanced Statements.................................................................................................................................414
Unbalanced Parentheses and Unescaped Quotes .........................................................................................414
Unrecognized Keywords ................................................................................................................................415
Reserved Word Mishaps ................................................................................................................................415
Invalid Date Literals .......................................................................................................................................416
Understanding Runtime Errors............................................................................................................................416
How Runtime Errors Work in AppleScript ......................................................................................................416
Understanding the Psychology of an Error.....................................................................................................419
Understanding the Anatomy of an Error.........................................................................................................419
Trapping Runtime Errors................................................................................................................................420
Generating Runtime Errors ............................................................................................................................425
Tips for Handling Runtime Errors...................................................................................................................428
Understanding Common Error Numbers .............................................................................................................431
xi
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ CONTENTS
Identifying Operating System Errors..............................................................................................................431
Identifying Apple Event Errors .......................................................................................................................432
Identifying Application Scripting Errors .........................................................................................................433
Identifying AppleScript Language Errors .......................................................................................................434
Summary ............................................................................................................................................................435
■Chapter 16: Interacting with the User .................................................................................. 437
Creating Basic Dialog Boxes and Gathering Text Input.......................................................................................437
Introducing the display dialog Command ......................................................................................................437
Introducing the display alert Command.........................................................................................................447
Introducing the choose from list Command...................................................................................................449
Choosing Files, Folders, and Disks .....................................................................................................................454
Introducing the choose file Command ...........................................................................................................454
Introducing the choose file name Command .................................................................................................460
Introducing the choose folder Command.......................................................................................................463
Choosing Other Types of Items ...........................................................................................................................465
Introducing the choose application Command ..............................................................................................465
Introducing the choose remote application Command ..................................................................................466
Introducing the choose URL Command..........................................................................................................467
Introducing the choose color Command ........................................................................................................468
Summary ............................................................................................................................................................470
■Chapter 17 Working with Files ............................................................................................. 471
Identifying Files, Folders, and Disks ...................................................................................................................471
Using Path Strings .........................................................................................................................................472
Using File System Objects .............................................................................................................................474
File URL Strings .............................................................................................................................................482
Reading and Writing Files ...................................................................................................................................483
Commands for Reading and Writing Files......................................................................................................483
Dealing with Text File Encodings...................................................................................................................495
Summary ............................................................................................................................................................502
■Chapter 18: Organizing Your Code with Handlers ................................................................ 505
What Are User-Defined Handlers? ......................................................................................................................505
Creating a Simple Handler ..................................................................................................................................507
Using Parameters ...............................................................................................................................................508
What’s the Result?..............................................................................................................................................509
Using the return Statement............................................................................................................................509
Working with Return Values ..........................................................................................................................510
Can a Handler Return More Than One Result? ..............................................................................................511
Specifying Handler Parameters ..........................................................................................................................512
Using Positional Parameters..........................................................................................................................513
Using Labeled Parameters.............................................................................................................................515
Introducing Recursion.........................................................................................................................................519
Using the run Handler in Scripts .........................................................................................................................520
I’ve Never Seen No run Handler!....................................................................................................................520
When Should You Make the run Handler Explicit?.........................................................................................521
Working with Handlers in Applets.......................................................................................................................522
Using the Standard Event Handlers ...............................................................................................................522
Using User-Defined Handlers from Other Scripts ..........................................................................................526
Tips for Designing and Using Handlers...............................................................................................................526
Organizing Code.............................................................................................................................................526
Reusing Code .................................................................................................................................................527
xii
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ CONTENTS
Thinking Ahead ..............................................................................................................................................527
Thinking Small ...............................................................................................................................................527
Reorganizing Existing Code ...........................................................................................................................528
Example Project: A Reusable Associative List ....................................................................................................529
Designing the Associative List .......................................................................................................................530
Writing the Essential Handlers.......................................................................................................................531
Writing the Extra Handlers .............................................................................................................................534
Revising the Design .......................................................................................................................................535
Conclusion .....................................................................................................................................................537
Summary ............................................................................................................................................................538
■Chapter 19: Organizing Your Code with Script Objects ........................................................ 541
Introducing Script Objects ..................................................................................................................................541
What Is a Script Library?................................................................................................................................542
What Is Object-Oriented Programming? ........................................................................................................543
Understanding Script Objects .............................................................................................................................543
Defining a Script Object in a Script................................................................................................................544
Loading and Storing Script Objects from Disk ...............................................................................................545
How Variable Scope Works in Script Objects.................................................................................................546
Working with Script Libraries .............................................................................................................................548
What Advantages Do Script Libraries Provide? .............................................................................................549
Creating Your First Script Library...................................................................................................................550
Where Should You Save Your Library?...........................................................................................................550
What Are the Options for Loading Script Libraries?.......................................................................................552
Beginning Object-Oriented Programming...........................................................................................................556
Your First Object: A Better Associative List....................................................................................................557
Extending Objects Through Inheritance.........................................................................................................563
Creating Plug-and-Play Objects.....................................................................................................................573
Summary ............................................................................................................................................................583
Part III: Putting AppleScript to Work ....................................................................................... 585
■Chapter 20: Scripting the File System .................................................................................. 587
How the Finder Represents the Mac OS X File System ......................................................................................587
Understanding Containers .............................................................................................................................589
Understanding Files .......................................................................................................................................592
Understanding Packages ...............................................................................................................................594
Understanding the computer-object Class ....................................................................................................594
How System Events Represents the Mac OS X File System ...............................................................................595
Understanding Files .......................................................................................................................................597
Understanding Folders...................................................................................................................................598
Understanding Disks......................................................................................................................................599
Understanding System Events’ alias Class ....................................................................................................599
Other Classes of Interest................................................................................................................................600
Working with Finder Items..................................................................................................................................602
Opening and Closing Items ............................................................................................................................602
Duplicating Files and Folders.........................................................................................................................603
Deleting Files and Folders .............................................................................................................................604
Moving Files and Folders ...............................................................................................................................605
Checking if Items Exist ..................................................................................................................................606
Making New Items .........................................................................................................................................606
Sorting Lists of Finder References.................................................................................................................607
Ejecting Disks ................................................................................................................................................608
xiii
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ CONTENTS
Selecting Items in a Finder Window ..............................................................................................................608
Converting Finder References to AppleScript Aliases....................................................................................608
More on Working with Folders............................................................................................................................610
Filtering the Content of Folders .....................................................................................................................610
Getting the Entire Contents of a Folder..........................................................................................................611
Locating Important Files and Folders with Standard Additions ..........................................................................612
Avoiding Hardcoded Paths to the Startup Disk and Home Folder..................................................................613
Getting the Path to the Currently Running Script...........................................................................................614
Getting Paths to Resources in an Application Bundle....................................................................................616
Mounting Volumes ..............................................................................................................................................618
Summary ............................................................................................................................................................621
■Chapter 21: Scripting Apple Applications............................................................................. 623
Scripting iTunes ..................................................................................................................................................623
Understanding the iTunes Object Model........................................................................................................624
Working with Sources....................................................................................................................................626
Working with Tracks and Playlists.................................................................................................................627
Example Project: My Themed Playlist............................................................................................................631
Scripting Mail......................................................................................................................................................635
Working with Mailboxes ................................................................................................................................636
Working with Messages.................................................................................................................................636
Creating Outgoing Messages .........................................................................................................................641
Working with Mail Rules ................................................................................................................................642
Example Project: Building a Monthly Message Archive .................................................................................646
Scripting iCal.......................................................................................................................................................650
Working with Calendars.................................................................................................................................652
Working with Events ......................................................................................................................................653
Scripting Address Book ......................................................................................................................................655
Working with People......................................................................................................................................656
Working with Groups .....................................................................................................................................659
Working with Rollovers ..................................................................................................................................661
Example Project: Looking Up Contact Information by Name..........................................................................663
Scripting Automator............................................................................................................................................666
Using the Run AppleScript Action ..................................................................................................................666
Scripting the Automator Application..............................................................................................................671
Summary ............................................................................................................................................................673
■Chapter 22: Extending AppleScript with Scripting Additions ............................................... 675
xiv
Introducing Scripting Additions and Scriptable Faceless Background Applications...........................................675
Scripting Additions in Detail ...............................................................................................................................677
Scripting Additions and the AppleScript Language .......................................................................................677
Installing Scripting Additions .........................................................................................................................678
Missing Additions and Garbled Scripts ..........................................................................................................679
Distributing Scripting Additions with Your Scripts.........................................................................................680
Understanding Scripting Addition Compatibility Issues .................................................................................683
Understanding Scriptable Faceless Background Applications............................................................................688
Installing Scriptable FBAs ..............................................................................................................................688
Distributing Scriptable FBAs with Your Scripts..............................................................................................688
Examples of AppleScript Extensions...................................................................................................................689
Built-in Extensions.........................................................................................................................................689
Third-Party Extensions...................................................................................................................................689
Using the Standard Additions Scripting Addition ................................................................................................690
Providing Audio Feedback .............................................................................................................................691
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ CONTENTS
Pausing Your Scripts......................................................................................................................................692
Getting and Setting the System Volume ........................................................................................................692
Getting System Information ...........................................................................................................................693
Working with URLs.........................................................................................................................................694
Using the Image Events Faceless Background Application ................................................................................695
Processing Text with the Satimage Scripting Addition.......................................................................................697
Downloading and Installing the Satimage Scripting Addition........................................................................698
Performing Simple Find and Replace Tasks ..................................................................................................698
Counting Occurrences of a Substring in a String...........................................................................................699
Finding and Replacing Substrings in a File....................................................................................................700
Searching and Replacing Across Many Files .................................................................................................701
Finding and Replacing Text with Regular Expressions ..................................................................................701
Batch-Changing File Names ..........................................................................................................................707
Summary ............................................................................................................................................................710
■Chapter 23: AppleScript Amenities....................................................................................... 711
Using the Services Menu ....................................................................................................................................711
AppleScript Editor Services ...........................................................................................................................712
Creating Your Own Services ..........................................................................................................................712
Scheduling Scripts with iCal ...............................................................................................................................715
Triggering Scripts with Folder Actions................................................................................................................716
Defining Event Handlers for Folder Actions ...................................................................................................717
Where Are Folder Action Scripts Stored? ......................................................................................................717
Managing Your Folder Actions .......................................................................................................................717
Creating Your First Folder Action ...................................................................................................................719
Controlling Applications with GUI Scripting ........................................................................................................722
Enabling GUI Scripting ...................................................................................................................................723
The GUI Scripting Dictionary ..........................................................................................................................723
GUI Scripting Object Structure .......................................................................................................................723
Basic GUI Scripting Examples ........................................................................................................................725
Using GUI Scripting Commands .....................................................................................................................726
Example Project: Searching in Preview .........................................................................................................728
Understanding the Limitations of GUI Scripting .............................................................................................735
Working with the Clipboard ................................................................................................................................736
Getting Clipboard Data into AppleScript ........................................................................................................736
Setting the Clipboard Data.............................................................................................................................737
Example Project: Creating PDF Cuttings from Selections in Preview ............................................................739
Summary ............................................................................................................................................................742
■Chapter 24: Scripting iWork and Office ................................................................................ 743
Scripting iWork ...................................................................................................................................................743
Scripting Pages..............................................................................................................................................744
Scripting Keynote...........................................................................................................................................751
Scripting Numbers .........................................................................................................................................758
Scripting Microsoft Office ...................................................................................................................................760
Working with Microsoft Entourage ................................................................................................................761
Working with Excel ........................................................................................................................................777
Working with Word ........................................................................................................................................788
Where Next? ..................................................................................................................................................791
Summary ............................................................................................................................................................792
■Chapter 25: Scripting Data and Databases........................................................................... 793
Automating FileMaker Pro with AppleScript .......................................................................................................794
xv
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ CONTENTS
The FileMaker Object Model and the Commands You Can Use .....................................................................795
Finding Data Quickly with the whose Clause.................................................................................................802
Running AppleScripts from Inside FileMaker Pro ..........................................................................................806
Scripting Runtime Labs’ MacSQL .......................................................................................................................807
Getting Connected .........................................................................................................................................808
Using a Simple select Command ...................................................................................................................809
More on Result Sets.......................................................................................................................................809
Some Useful Handlers....................................................................................................................................810
Database Events .................................................................................................................................................812
Database Events Classes and Commands .....................................................................................................812
Database Events Examples............................................................................................................................813
Summary ............................................................................................................................................................814
■Chapter 26: Scripting Adobe InDesign.................................................................................. 817
Learning by Example ..........................................................................................................................................818
Understanding the InDesign Object Model..........................................................................................................820
How InDesign Organizes Its Many Properties ................................................................................................820
How InDesign Manages Units of Measurement .............................................................................................823
How to Set Properties Safely when Making New Objects .............................................................................824
Working with Documents....................................................................................................................................825
Working with Document Layers.....................................................................................................................829
Understanding InDesign References..............................................................................................................831
Working with Text...............................................................................................................................................831
Working with Text Stories..............................................................................................................................832
Working with References to Text...................................................................................................................833
Working with Graphics........................................................................................................................................835
Drawing Lines .....................................................................................................................................................836
Example Project: An InDesign Scripts Launcher.................................................................................................837
Working with Tables ...........................................................................................................................................840
Importing Table Text from a Spreadsheet .....................................................................................................841
Copying Formatting Between Cells................................................................................................................843
Working with Selections .....................................................................................................................................845
Example Project: Captioning a Selected Graphic...........................................................................................846
Example Project: Cleaning Up Selected Text .................................................................................................848
Labeling Objects for Use in Workflow Scripts.....................................................................................................850
Taking Advantage of AppleScript-Specific Preferences .....................................................................................852
Example Project: Replacing Tags with Images ...................................................................................................854
Preparing InDesign ........................................................................................................................................855
Processing the Tags.......................................................................................................................................856
Preparing the Image Files..............................................................................................................................857
Placing the Graphics ......................................................................................................................................858
Testing the Script...........................................................................................................................................860
Using InDesign on a Server.................................................................................................................................860
Summary ............................................................................................................................................................861
■Chapter 27: Interacting with the Unix Command Line .......................................................... 863
xvi
Why and When Are Shell Scripts Used in AppleScript? ......................................................................................863
Understanding Unix Scripting Concepts .............................................................................................................864
The Unix Command Line and Mac Desktop Compared ..................................................................................864
How the Unix Command Line Works..............................................................................................................865
Getting Help ...................................................................................................................................................869
Things to Watch Out For ................................................................................................................................870
Some Useful Unix Commands........................................................................................................................872
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ CONTENTS
Running Shell Scripts from AppleScript..............................................................................................................873
Scripting the Terminal Application.................................................................................................................873
Using the do shell script Command ...............................................................................................................875
Assembling Shell Script Strings.....................................................................................................................879
Passing Data to Standard Input .....................................................................................................................883
Running AppleScript from Shell Scripts..............................................................................................................886
Using the osascript Command .......................................................................................................................886
Passing Parameters to the Script ..................................................................................................................887
Other Related Commands ..............................................................................................................................888
Example Projects ................................................................................................................................................888
Simple Text Processing Handlers ..................................................................................................................888
Changing File System Permissions................................................................................................................890
Analyzing PDF Files........................................................................................................................................893
Summary ............................................................................................................................................................896
■Chapter 28: Using Smile: The AppleScript Integrated
Production Environment ................................................................................................. 897
Introducing Smile................................................................................................................................................897
Introducing Smile’s Integrated Engine Architecture ......................................................................................897
About Smile’s Terminal..................................................................................................................................898
Why Should You Use Smile? ..........................................................................................................................898
Downloading Smile .............................................................................................................................................899
Using Smile.........................................................................................................................................................899
Using the AppleScript Command-Line Environment......................................................................................900
Using Smile’s Custom Dialog Boxes ..............................................................................................................901
Using Regular Expressions ............................................................................................................................903
Using the Graphic Engine...............................................................................................................................904
Using SmileLab ..............................................................................................................................................905
Example Project: Adding Text to a PDF Document .............................................................................................908
Preparing the PDF..........................................................................................................................................908
Rolling Up the Scripts into a Graphical Interface ...........................................................................................915
Further Exercises...........................................................................................................................................925
Summary ............................................................................................................................................................926
■Chapter 29: Tips and Techniques for Improving Your Scripts .............................................. 927
Design, in a Nutshell...........................................................................................................................................928
Taking Your Scripting Skills to the Next Level ...............................................................................................928
How Much Design Do Your Scripts Need? .....................................................................................................929
Starting Out Is Hard (But Gets Easier with Practice) ......................................................................................931
How the Design-Driven Approach Changes the Way You Think About Code .................................................933
Testing and Debugging Your Code......................................................................................................................934
General Testing Tips and Techniques............................................................................................................935
Debugging in AppleScript Editor ....................................................................................................................938
Debugging in Script Debugger.......................................................................................................................941
Keeping Track of Changes .............................................................................................................................944
Improving the Performance of Your Code...........................................................................................................948
The Dos and Don’ts of Optimization...............................................................................................................948
Common AppleScript Optimizations ..............................................................................................................951
Advanced Optimization Techniques...............................................................................................................956
Summary ............................................................................................................................................................966
■Chapter 30: Creating Cocoa Applications with AppleScriptObjC .......................................... 969
Example Project: HelloAppleScriptObjC ..............................................................................................................970
Creating the Project in Xcode ........................................................................................................................971
xvii
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ CONTENTS
Adding the AppleScript Code in Xcode ..........................................................................................................973
Constructing the Interface in Interface Builder..............................................................................................973
Building and Testing the Application .............................................................................................................979
Understanding How Cocoa Works.......................................................................................................................980
Understanding Outlets ...................................................................................................................................980
Understanding Targets and Actions...............................................................................................................980
How AppleScript Interacts with Cocoa Objects..............................................................................................982
Modifying HelloAppleScriptObjC to Set the Text Field ........................................................................................983
Updating the Code and Testing the Changes.................................................................................................983
What Is All That Code in the Default AppleScript File? ..................................................................................983
Example Project: PlaySound ...............................................................................................................................985
Creating the Project and Adding the Code .....................................................................................................985
Constructing the Interface .............................................................................................................................986
Building and Testing the Application .............................................................................................................987
Understanding How It Works .........................................................................................................................988
Viewing the Cocoa Documentation in Xcode ......................................................................................................990
How Cocoa Classes Are Documented ............................................................................................................991
How Cocoa Methods Are Documented...........................................................................................................993
Example Project: SnapShot.................................................................................................................................996
Creating the Project and Starting the Code ...................................................................................................996
Constructing the Interface .............................................................................................................................996
Completing the Code......................................................................................................................................997
Understanding How It Works .........................................................................................................................999
Preparing the Text Fields Using an awakeFromNib Handler........................................................................1000
Building and Testing the Application ...........................................................................................................1001
Modifying SnapShot to Use Cocoa Bindings .....................................................................................................1001
Adjusting the Code for Bindings ..................................................................................................................1001
Setting Up Bindings in Interface Builder......................................................................................................1002
Building and Testing the Application ...........................................................................................................1006
Modifying PlaySound to Use Bundled Sound Files............................................................................................1006
Adding the Sound File Resources to the Project..........................................................................................1006
Adding the Code...........................................................................................................................................1007
Adding the Pop-Up Button ...........................................................................................................................1007
Building and Testing the Application ...........................................................................................................1007
Understanding How It Works .......................................................................................................................1008
Example Project: KitchenTimer.........................................................................................................................1009
Creating the Project and Starting the Code .................................................................................................1009
Constructing the Interface ...........................................................................................................................1010
Completing the Code....................................................................................................................................1013
Extra Exercises .................................................................................................................................................1015
Where Next? .....................................................................................................................................................1016
Summary ..........................................................................................................................................................1017
Conclusion ........................................................................................................................................................1018
■Index................................................................................................................................... 1019
xviii
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ INTRODUCTION
Foreword
One of the inherent tensions in product design is the balance between generality and specificity.
Products are designed to appeal to a wide range of users, yet each individual has specific needs
and problems that cannot be anticipated.
Custom products are usually much more expensive than generic ones. This is true for clothing,
automobiles, medicine, and of course software. Custom products are also more difficult to create.
Even worse, a person's needs may change over time, so something that worked when it was
purchased may not be as useful in another time or situation.
Unlike physical products, software is infinitely malleable. In theory, at least, it can do (almost)
anything you want and be specialized to your needs. In practice, software designers have to
anticipate what users are most likely to want. Building in every possible option would make the
software very powerful but completely unusable. With this in mind, Mac software developers
tend to focus on simplicity and elegance. This is a cultural value that has grown up with the Mac
OS and now permeates every aspect of the Mac experience. The idea is to carefully design just the
right product while avoiding unnecessary features.
But what if the end result is not quite right for you? When it comes to software, the human usually
learns to adapt to fit the software, rather than the other way around. It's as if the tailor adjusts
your body to fit the suit, rather than the suit to fit you. But there is another solution, which is to
make the software itself more customizable. Again, it’s not possible to anticipate everything that
anyone would want. This is a difficult problem, then, to build software applications that are
simple and elegant, yet infinitely customizable to suit unknown needs.
This is the vision behind AppleScript: to enable users to extend, combine, and customize software
to suit their own specific needs. AppleScript is not just a scripting language. It is an approach to
customizable and extensible software development, which has been adopted by hundreds of
applications on the Mac. AppleScript is designed to create a network effect in software, where the
more applications that use AppleScript the better it is for everyone. This is a grand vision, but the
reality is not so simple. Scripting and customizing applications is not something that everyone
does every day. It requires some technical knowledge and practical examples to follow.
xix
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ FOREWORD
This book is an essential guide to AppleScript and related technologies. The key value of the book
is that it integrates a clear presentation of the vision and purpose of AppleScript with the
mundane technical details of writing scripts and getting useful work done. When talking about
scripting, it’s easy to get lost in the details. When writing a foreword, like this, it’s easy for me to
present a grand vision that seems appealing. The benefit of this book is that it combines and
connects the vision with the practical reality.
Dr. William Cook
Associate Professor
Department of Computer Science
University of Texas at Austin
AppleScript Architect and Engineering Manager
Apple Computer, 1991–1993
xx
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ INTRODUCTION
About the Authors
Licensed by
Jim Kilcullen
2884260
Hamish Sanderson is a 10-year veteran of AppleScript and a professional automation developer
living and working in the UK. Over the years he has contributed a range of useful libraries and
utilities to the AppleScript community and pops up with some regularity on the various
AppleScript mailing lists. He is also the author of the highly regarded appscript library, which
brings AppleScript-style application scripting support to the Python, Ruby, and Objective-C
languages on Mac OS X. He can be reached at hhas@users.sourceforge.net.
Hannan Rosenthal is the founder of Custom Flow Solutions LLC. He started
his media automation consulting firm in 1990, whose clients are now The
New York Times, Thomson Reuters, Associated Press, and Fidelity
Investments. Since then he helped reshape the workflow of numerous
publishing companies creating systems that save their owners millions of
dollars and thousands of hours annually.
Hanaan is a speaker in MacWorld Expo and Seybold Seminars. Hanaan and
his wife, Johanne, home-school their two children and restoring their solarpowered Victorian home in Providence, RI. In his spare time, Hanaan likes to
pour concrete kitchens, sculpt, photograph, write and generally get into
trouble in any way possible. He can be reached at applescript@hanaan.com.
xxi
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ FOREWORD
About the Technical
Reviewer
David A. Coyle earned his Ph.D. in thermochronology in 1992. Research in thermal modeling and
crustal evolution at the Max-Planck Institute for Nuclear Physics (Heidelberg, Germany) lead to a
career in software development. David has been concentrating on Apple technologies since 1997
and is a certified Apple System Administrator.
xxii
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ INTRODUCTION
Acknowledgments
We would like to thank the many people who have worked long and hard to make this book
possible.
Many thanks to our guest authors—Emmanuel Levy, Harald Monihart, Ian Piper, Shane Stanley,
Barry Wainwright, and Craig Williams—for sharing their knowledge and experience with us.
Many thanks to David Coyle for helping to get the technical details right and to Bill McManus for
ensuring all of the other words made sense too.
Many thanks too to Rob and Mark for their feedback on draft chapters and to Debra, Douglas,
Kylie, Clay, and the rest of Apress for supporting this project through a long and sometimes
arduous development process.
Lastly, many thanks to Dr William Cook for gracing us with his insights into the philosophy and
goals of AppleScript and to all of the AppleScript engineers, application developers, and
community members for a network effect where the copious sharing of knowledge and
enthusiasm is every bit as important as the myriad interactions of bits and bytes.
xxiii
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ FOREWORD
Introduction
Welcome to the third edition of Learn AppleScript: The Comprehensive Guide to Scripting and
Automation on Mac OS X. This book will teach you the principles and practices of controlling the
many “AppleScriptable” Mac OS X applications using the AppleScript scripting language
included in Mac OS X.
The title of this book represents a challenge: just how do you create a comprehensive guide to a
subject as broad and deep as automating your Mac with AppleScript?
While we do cover every aspect of the AppleScript language in extensive detail, obviously we
cannot hope to cover every last scriptable application on the market today. Instead, we will
explain the core principles by which all scriptable applications operate, before exposing you to a
broad range of very different applications—from simple and familiar tools such as TextEdit and
Finder, through popular lifestyle applications such as Mail and iTunes, and on to professional
productivity programs such as Microsoft Office and Adobe InDesign.
Although you may not use all of these applications in your daily routine, we hope that you will
take the time to explore them here. Exploring the wide range of applications covered here will
help to familiarize you with the many similarities (and differences) found among scriptable
applications today—knowledge that will provide essential guidance and inspiration as you go on
to learn and use other scriptable applications for yourself.
While this book is designed for Mac users who have never scripted before, we have ensured that
there is plenty of material here to engage more experienced AppleScripters, as well as
professional programmers coming to AppleScript from other languages. So without further ado,
let’s look at how you can get the most out of this book whatever your background is.
If You Have Never Scripted Before…
If you have never scripted before, don’t worry! This book was designed with you foremost in mind.
Part 1 of the book will start you off with a very gentle introduction to AppleScript and application
scripting concepts and techniques. Learning to script is not a five-minute task; there is a lot of
information to absorb, and it takes time and practice to master. To help you get to grips with
these subjects, Chapter 2 divides them into eight “Key Concepts”—four for the AppleScript
language, four for application scripting—to provide you with a roadmap of what you will learn
xxiv
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ INTRODUCTION
over the course of the book and help you to fit the pieces together as you go. Chapter 3 then leads
you through the process of creating your first practical AppleScript.
Part 2 begins with an introduction to Mac OS X’s AppleScript Editor, where you will write and test
the majority of your scripts throughout this book. Next, Chapter 5 takes you on a grand tour of the
four key concepts behind application scripting, helping you develop a robust understanding of this
incredibly powerful technology in preparation for Part 3 of the book. Chapters 6 to 17 then guide
you through the first three key concepts that underpin the AppleScript language itself, equipping
you with all the knowledge you need to start writing scripts of your own. Chapters 18 and 19 cover
the fourth key concept behind AppleScript, although as this material is more advanced you might
wish to skip it for now and come back to it later when you are ready to learn more.
Part 3 of the book provides you with lots of opportunity to put your newfound knowledge to
practical use, as you explore a wide range of popular scriptable Mac OS X applications in
Chapters 20 to 23 and learn how to extend the functionality of the AppleScript language through
the use of scripting additions.
As your confidence grows, you might like to tackle some of the larger, more advanced
applications covered in Chapters 24 to 28. Or you might wish to return to Chapters 18 and 19 to
complete your knowledge of AppleScript’s most advanced language features before Chapter 30
launches you into the exciting world of GUI application development with Snow Leopard’s new
AppleScriptObjC bridge.
If You Are Already an AppleScript User…
If you are an existing AppleScript user keen to expand your knowledge and hone your skills, you will
find lots of valuable information throughout this book, particularly in Parts 2 and 3. I recommend
you start with a quick read through Part 1, just to familiarize yourself with the planned structure of
the book, before diving into the areas of Parts 2 and 3 that interest you the most.
As with previous editions, Part 2 provides an extensive reference to every facet of the AppleScript
language itself, while Part 3 gets down and dirty with the practical business of automating your
desktop. However, this new edition expands both the breadth and depth of our coverage of
AppleScript and application scripting with several hundred pages of completely new material!
In addition to ensuring a robust understanding of basic AppleScript features—objects,
commands, operators, variables, and flow control statements—we dig deeply into the more
advanced and obscure corners of AppleScript. Chapters 7 and 17 include detailed discussion of
Unicode text and text file encodings—essential background knowledge for reading and writing
text files in AppleScript. Chapter 17 clarifies the sometimes confusing world of AppleScript’s alias,
file, and POSIX file classes, explaining just how they work and how to use them effectively.
Chapters 18 and 19 provide detailed coverage of handlers and script objects—powerful features for
organizing large, sophisticated scripts. Along the way, we show you how to package your handlers
as reusable libraries for easy sharing between many scripts and provide an AppleScript-friendly
introduction to object-oriented programming as you learn how to design and use your own
“classes” of objects. With the introduction of Snow Leopard’s exciting new AppleScriptObjC bridge,
these features and techniques are more important to AppleScript developers than ever before.
Chapter 22 will help you navigate the practical issues involved in installing and using scripting
additions across a range of Mac OS X architectures: PowerPC and Intel, 32- and 64-bit. Guest
author Ian Piper also contributes an introduction to advanced text processing with the popular
Satimage scripting addition.
xxv
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ INTRODUCTION
As before, we cover a good range of popular Mac OS X applications—including the Finder, Mail,
iCal, and the ever-present iTunes—giving you plenty of opportunity to hone your automation
skills. In addition, two new guest chapters provide in-depth coverage of a number of important
productivity applications. Chapter 24, contributed by Harald Monihart and Barry Wainwright,
explores the iWork and Microsoft Office application suites, while Chapter 26 provides an
extensive introduction to one of the great heavyweights of Mac OS X automation, Adobe
InDesign, under the guidance of InDesign scripting expert, Shane Stanley.
Chapter 27 explains the ins and outs of integrating the AppleScript language with the powerful, if
cryptic, Unix command line that lies just beneath the surface of the Mac OS X operating system,
while Chapter 28 explores the highly versatile Satimage Smile platform in the company of guest
author Emmanuel Levy.
In Chapter 29, we step back from the day-to-day practicalities of AppleScripting to examine the
bigger picture behind scripting and programming in general. While this chapter is by no means
required reading, we hope that it will provide valuable inspiration and practical knowledge that will
aid you as you look to design, debug, and optimize your scripts more effectively.
Finally, in Chapter 30, guest author Craig Williams introduces you to one of the most exciting
AppleScript developments of recent years: Snow Leopard’s new AppleScriptObjC bridge.
AppleScripters can now directly harness the enormous power of Mac OS X’s Cocoa programming
frameworks to develop highly polished and capable GUI applications of their own.
If You Are an Experienced Programmer…
If you are an experienced programmer looking to develop some AppleScript skills, you will find
this book to be a valuable reference guide.
While the AppleScript language itself is surprisingly small and simple, the English-like syntax can
take some getting used to if you are more familiar with dot-style languages such as Python and Ruby
or curly-brace languages such as Objective-C and Java. Remember, AppleScript syntax is designed
to be easily read by nonprogrammers, so the trade-offs it makes are different from those made by
these other languages, but with a little time and practice I’m sure you’ll get the hang of it too.
The real challenge will be in forming a full and accurate understanding of how application
scripting works. AppleScript’s command and reference syntax may resemble that of objectoriented programming—but don’t be fooled by appearances! AppleScript’s conceptual roots lie
as much in procedural and relational database programming as in the more familiar world of
OOP. (To use a rough analogy, think of sending Apple events as a bit like sending XPath queries
over XML-RPC.) While we may not employ such technical terms throughout this book, the
information you need to make sense of this powerful, if unusual, technology is all in there.
You may find the pacing a little slow for your taste and the detailed discussion of basic
programming language concepts such as variables, values, and flow control to be somewhat
redundant at your level. However, all the essential information you require is in here: the features
and capabilities of the AppleScript language, and the principles and practices of application
scripting. Nor do we shy away from “advanced” AppleScript topics such as module management
and object-oriented programming with script objects, or essential optimization techniques for
getting the best performance out of your application automation code.
We recommend you quickly skim the introductory material in Part 1 before moving on to the real
meat in Parts 2 and 3. You’ll find Chapters 6 and 12 especially valuable in understanding how
application scripting works, while Part 3 provides lots of hands-on experience in working with a
wide range of scriptable applications and explains how to integrate AppleScript with the Unix
command line and Objective-C/Cocoa environments.
xxvi
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ INTRODUCTION
Resources
Here are some links to useful online AppleScript-related resources:
The Apple web site provides several AppleScript-related mailing lists
(http://www.lists.apple.com/mailman/listinfo), including the AppleScript-Users
mailing list, which is a great place to meet other AppleScript users and get your
questions answered. An AppleScript bulletin board is also available at
http://discussions.apple.com (you’ll find it in the Mac OS X Technologies section).
The Apple web site’s developer section (http://developer.apple.com) includes a range
of AppleScript-related material aimed at intermediate and advanced AppleScript users
and scriptable application developers, such as the AppleScript Language Guide
reference documentation.
MacScripter (http://www.macscripter.net) is a terrific community-driven web site
where you can find scripting additions, AppleScript code shared by other scripters, a
BBS, and many other AppleScript-related resources.
The Mac OS X Automation web site (http://www.macosxautomation.com) provides useful
information on AppleScript and other automation technologies found in Mac OS X. The
AppleScript section includes links to a range of other AppleScript-related web sites.
More-advanced readers might also wish to check out Dr. William Cook’s HOPL III
conference paper on the early history of AppleScript. Dr. Cook’s paper provides many
fascinating insights into the philosophy and workings of the AppleScript language and
application scripting technologies and is available from his web site
(http://userweb.cs.utexas.edu/users/wcook) as a downloadable PDF.
Many other AppleScript-related web sites exist that I haven’t included here. Some are given in
later chapters, others can be found via the previous links provided or by searching online.
Formatting Conventions Used in This Book
To aid readability, we have used a few simple formatting conventions in this book:
The ¬ symbol is used in example scripts to indicate where a long line of code has been
wrapped to fit the printed page. AppleScript also uses this symbol to indicate line
continuations, so you can type it as-is if you wish, but its position may change when the
script is compiled. Alternatively, you can omit both this symbol and the line break that
follows it and allow the entire line to wrap naturally within the AppleScript Editor
window.
The --> character sequence at the start of a line is used to indicate a typical value
returned by a script when it is run and is not . The double-hyphen sequence (--) is also
used by AppleScript to indicate a single-line comment, so it doesn’t matter if you type
this line when entering a script into AppleScript Editor (though see the next point).
Where a return value indicated by the --> character sequence is too long to fit on a single
line, it may be spread across subsequent lines like this:
--> {application file "Address Book.app" of folder "Applications" of
startup disk of application "Finder", application file "Automator.app"
of folder "Applications" of startup disk of application "Finder", ...}
If you choose to type this text into AppleScript Editor, make sure you remove all of the
line breaks so that it appears as a single line, otherwise the script will not compile
correctly.
xxvii
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
■ INTRODUCTION
We regularly use the phrase “application object” to mean any object that is defined by a
scriptable application—a folder object, a playlist object, and so on. Most scriptable
applications also define a top-level object whose class is application, so when we discuss
these objects in particular, the word “application” is shown in monospace text to make
the distinction clear; for example, “the Finder’s application object.”
Errata
We have made every effort to ensure that there are no errors in the text or code. However,
mistakes happen, and we recognize the need to keep you informed of any mistakes as they’re
discovered and corrected. An errata sheet will be made available on the book’s main page at
http://www.apress.com. If you find an error that hasn’t already been reported, please let us know.
The scriptable applications used in this book were the latest versions available at the time of
writing, though newer releases may appear over time. While scripts written for one version of an
application will usually work with newer versions, this is not always the case. If you discover a
script no longer works due to non-backwards-compatible changes in the software used, please let
us know and we will try to address such issues where possible.
xxviii
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
1
Part
I
Welcome to AppleScript
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
3
Chapter
1
Introducing AppleScript
Licensed by
Jim Kilcullen
2884260
AppleScript is a scripting language for automating your Mac. With AppleScript’s help,
many tasks that you would normally perform with the mouse and keyboard can be
turned over to your Mac to deal with, freeing you up to get on with more interesting or
important things.
What is AppleScript good for? AppleScript’s greatest strength is its ability to
communicate with hundreds, if not thousands, of Mac OS X applications. This makes it
ideal for all kinds of application scripting tasks—anything from simple, one-off scripts
that you run once to perform a particular task, up to large, complex workflows that will
perform vital functions for months or even years to come. In fact, most of the power of
AppleScript comes not from the language itself, but from the applications it talks to.
What makes AppleScripting worthwhile? Although many of the tasks you carry out on
your Macintosh are interesting and unique, many other, day-to-day tasks are boring and
repetitive, requiring you to perform the same sequence of actions over and over again. If
you write some scripts to take care of the latter, the time you save can be spent on more
of the former.
Automating with AppleScript: From Small Tasks to
Large
AppleScript is great for creating small, simple scripts, each of which performs a single
task many times over—providing significant, immediate benefits to even the most casual
of users. In the hands of an experienced developer, AppleScript can also scale to large
and complex tasks, to assemble a whole series of professional Mac applications into
powerful and sophisticated workflows.
Let’s consider an example of each.
Automating Small Tasks
Creating small, simple scripts is the ideal way for you to start to become familiar with
AppleScript. AppleScript lets you easily create a script, test it, save it as a file or
3
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
4
CHAPTER 1: Introducing AppleScript
application, and start using it. This quick turnaround for truly useful utilities is part of the
winning recipe that makes AppleScript so great.
A few years ago I was teaching an Adobe Photoshop class, and during my five-minute
break, a colleague told me about a problem a client of his, a prepress house, was
having. The client couldn’t print lines in QuarkXPress documents that were thinner than
0.25 point and was spending hours correcting every document. By the end of my break I
had written the following script, saved it as an application, and handed it to him:
tell application "QuarkXPress 4.01"
tell every page of document 1
set width of (every line box whose width < 0.25) to 0.25
end tell
end tell
The prepress shop was thrilled with the “utility” we had scrambled to program for them.
Because the client got this one for free, its return on investment (ROI) can’t be measured
in terms of money. But just for kicks, we can figure out the ROI in terms of time. Again, I
created the script in five minutes. Without the script, it took an employee of the prepress
facility ten minutes to fix an average file manually, and this prepress facility printed ten
files a day. Using these numbers, the time investment paid for itself 5000 times over
during the first year (5 minutes invested saved approximately 100 minutes a day, which
corresponds to 500 minutes in a five-day work week, or 25,000 minutes in a 50-week
work year). This sounds a bit over the top, but it’s not. Little AppleScript efforts can
make a big difference.
Automating Large Tasks
While AppleScript doesn’t sweat the small stuff it can also be the base for large-scale
custom integrated systems. Large-scale automated solutions can provide impressive
savings in time and money over the long term, but they can also require significant time
and work to develop in the first place. Before you convert a long and complex manual
workflow into an AppleScript-based one, the first thing you need to do is determine
whether or not the process will be worth automating.
For example, here is a process that is not so suitable for automation:
You read the client’s instructions file to figure out what corrections the client wants.
If the client wants an image to be color-corrected, you open the image in Photoshop
and apply curves until it looks better. Otherwise, just correct the typos in the
InDesign document.
This process is much too arbitrary and relies on the operator’s human qualities such as
the ability to perform color correction and to correct typos. Although you might manage
to identify one or two small tasks that could be streamlined by the addition of small
utility scripts, the overall process will work best if left as a manual workflow.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 1: Introducing AppleScript
5
Here is a better candidate for automation:
When you get a job from a client, you search for the client in your FileMaker Pro
database to locate the job information. If the job is marked “urgent,” you notify the
imaging room via e-mail to expect the job within ten minutes. You open the Adobe
InDesign document and verify that all the fonts were provided. You make sure the
document contains the number of pages indicated in the electronic job ticket; if it
doesn’t, you make a note in the database and e-mail the client from Mail. After you
finish all these tasks, you use the Finder to make a copy of the “job” folder in the
“archive” folder on the server, and you send another copy to the “in” folder on the
production server. You repeat these steps for all jobs that arrived last night.
This is a process for which AppleScript is perfect because
It deals with lots of information, all of it in electronic form.
It follows clear, logical rules in deciding what to do with that data.
It must be repeated, step for step, for each one of the many client jobs
that arrive.
Accuracy is important, as any mistakes will mean time and money
are lost.
Note that all the steps in the process happen in software applications. The operator has
to know how to use FileMaker Pro to search for and enter data; how to use InDesign to
check fonts, pages, and so on; how to use Mail to send e-mail messages; and how to
use the Finder to move folders. The great news is that all of these applications include
extensive AppleScript support.
Controlling these and many other applications is one of AppleScript’s main strengths.
AppleScript can give commands to applications and get information from applications,
such as retrieving the data in a FileMaker Pro record or the number of pages in an
InDesign document.
When to Automate (or Not)?
Regardless of whether you write small- or large-scale scripts, one key question to ask
yourself is always the same: is the task worth automating? In other words, is the time
and/or cost of creating an automated solution less than the time and/or cost of doing
the job manually?
For example, a task that probably won’t benefit from automation is the retouching of
photographs. Although there may be many photographs to process (repetition), each
photograph is sufficiently unique that a human operator will be required to decide
exactly what changes—adjustments to highlights and shadows, removal of blemishes,
and so on—are necessary on a case-by-base basis.
However, even with tasks that require extensive manual intervention, you may find that
certain aspects of the job can be performed by a well-aimed script, making the human
operator’s job a bit easier. For example, if a client requires a low-resolution JPEG
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
6
CHAPTER 1: Introducing AppleScript
thumbnail to be created for each of the original, high-resolution images, you could ask
the retoucher to save a second copy of each file once they have finished correcting it.
Alternatively, the retoucher could save all of their finished files to a folder and then run a
script that opens each file in turn and resaves it as a JPEG file to another folder,
enabling the retoucher to get on with the next client’s work while the script runs.
The Golden Triangle: Scriptable Applications, the
AppleScript Language, and the Scripts You Write
Have you ever traveled to a foreign country where you don’t speak the local language
and are unfamiliar with local customs? Until you find your way around the place, it’s
easy to feel a bit overwhelmed by it all, perhaps even intimidated. If this is your first trip
into the world of AppleScript, or scripting in general, you will probably start getting this
feeling very shortly.
What you need is a map; one that provides a general overview of the entire territory,
shows you where the important landmarks lie, and points you toward some of the safer,
simpler, and/or more interesting paths that you can go on to explore for yourself. This
chapter is…not that map. In fact, this chapter is more of a map to the real map, which
you’ll meet in the next chapter. For now, I want to introduce you to three basic concepts
in the AppleScript world: scriptable applications, the AppleScript language, and the
scripts you write.
What Is a Scriptable Application?
As a Macintosh user, you likely already use many Mac OS X desktop applications, are
familiar with the graphical user interfaces (GUIs) that these applications present—
menus, buttons, text boxes, and so on—and know how to manipulate these GUIs using
a keyboard and mouse.
However, did you know that many of these applications also have a second interface,
one that’s invisible to ordinary human users but can be freely accessed by other Mac
OS X applications running on the same or even other machines? This invisible interface
allows one Mac application to take control of another—for example, to open a file,
manipulate its content, and save it again. In some cases, applications may interact in
this way purely for their own benefit; for example, the operating system occasionally tells
all the currently running applications to quit themselves so that it can safely shut itself
down. More often than not, however, these invisible application interfaces are actually
being used by scripts written by human users, to perform actions for our benefit. In
honor of this type of usage, we commonly refer to the application being controlled as a
“scriptable application.”
The driving force behind these hidden application interfaces is a special sort of
instruction, known as an Apple event, that can be passed from one running application
to another. The AppleScript language not only knows how to speak Apple events, it was
created with exactly that purpose in mind.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 1: Introducing AppleScript
7
TIP: Applications that understand Apple events are often also referred to as “AppleScriptable
applications,” although technically AppleScript is not the only language that can speak Apple
events.
I will talk a little more about Apple events later in the book, although in day-to-day
scripting you rarely should need to think about them yourself because AppleScript looks
after these low-level details for you.
Application scripting is such a large and important subject that it will take a couple of full
chapters just to build up a basic understanding of all the concepts and features behind
it, plus several more to really see what it can do when used to interact with real-world
applications such as Finder, iTunes, Mail, FileMaker Pro, Adobe InDesign, Microsoft
Word…the list of possibilities goes on and on!
For now, there are a couple of really basic application scripting concepts I’d like to
introduce you to, partly to give you an idea of what to expect and partly to whet your
appetite for what’s to come. These two concepts are objects and commands.
Introducing Objects
Objects are things. A kettle is a thing. A dog is a thing. In scriptable applications, the
things you deal with are pieces of information: a piece of music, a QuickTime movie, an
e-mail message from a friend or colleague, and so on. Some pieces of information may
even bemade up of smaller, simpler pieces of information: a movie consists of both an
audio track and a video track; an e-mail message has a subject, a sender, one or more
recipients, and a message body.
A Mac application has its own ways of representing these pieces of information in its
GUI, in a form that human users can understand. For example, an e-mail message in
Mail is represented by a window, and each section of the message is represented by a
different text box in that window. Similarly, the application’s scripting interface needs to
represent these pieces of information in a form that other applications can understand.
These representations are called objects.
However, although making all this information visible to you and your scripts is great,
information on its own isn’t enough to do anything useful—you also need some way to
usefully manipulate that information. Which brings us to our second concept:
commands.
Introducing Commands
Commands are instructions. “Boil” is an instruction. “Sit” is an instruction. All desktop
applications should respond to a few standard commands such as run, open (to open
one or more files), and quit. Individual applications may also define additional
commands for themselves—for example, iTunes provides commands for starting and
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
8
CHAPTER 1: Introducing AppleScript
stopping the playback of music and movies; Mail provides commands for creating a new
outgoing e-mail message and sending it.
These commands allow a scriptable application to be manipulated by other programs,
just as the menus and buttons in its GUI allow it to be manipulated by human users. If
the open and quit commands sound familiar, that’s probably because most applications
have Open and Quit menu options with the same names that fulfill the same functions, if
not necessarily in exactly the same way (the open command does not use a file chooser
dialog box, for example).
What’s more, many commands can be combined with objects to perform all sorts of
specific and sophisticated operations. For example:
Boil the kettle.
Tell the dog to sit.
Okay, so I don’t actually know of any Mac OS X applications that support these two
particular operations. However, before we look at some real application commands, I
need to introduce the other two concepts in the golden triangle…
What Is the AppleScript Language?
The first thing you should know about today’s computers (if you haven’t already noticed)
is that they are dumb; really, really dumb. To do anything useful at all, they require
extremely simple, absolutely precise instructions. I’m not just talking about “play the first
music track in iTunes” or “send the frontmost e-mail message in Mail” either; I mean
“read 4 bytes of data from memory location X, sum it with 4 bytes of data from memory
location Y, and store the result in memory location Z” simple.
Obviously, creating complex modern desktop applications like iTunes or Mail directly
using such low-level instructions would take an extremely long time. To speed up
software development (and no doubt preserve their sanity too), computer programmers
have created their own higher-level instruction sets that sit on top of the very low-level
instructions used by your computer’s hardware. This allows them to write much simpler
statements such as “z = x + y” and leave the computer to take care of all the nitpicky
details involved in fiddling with bits and bytes. These high-level instruction sets are
called programming languages. They provide a sort of halfway house between the
extremely primitive instructions used by computer hardware and the incredibly complex
and sophisticated languages normally used by humans; a place where humans and
computers can meet and (hopefully!) understand each other.
Over the years, many of these languages have been created to cater to a huge range of
different tasks: advanced mathematics, heavy-duty business data management, general
system administration, desktop- and web-based application development, and so on.
While many of these languages have been designed for programmers by programmers,
every so often a language comes along that is designed to appeal to nonprogrammers—
ordinary users like you and me—as well. AppleScript is one such language.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 1: Introducing AppleScript
9
Originally developed by Apple in the early ’90s, and included in every version of Mac OS
since System 7.1, AppleScript is, at its heart, a pretty simple tool. It provides objects to
represent various basic types of information that scripters regularly work with (numbers,
text, etc.), along with commands and other kinds of instructions that can be used to
manipulate that information. In addition, it provides several extremely useful structures
that can be used to control if and when these instructions should be performed, and a
couple of particularly powerful features that more advanced scripters can use to
organize their code.
None of these features is unique to AppleScript, however; many other scripting
languages also have them. So what makes AppleScript so special? Two features stand
out in particular.
The first is AppleScript’s ability to speak Apple events, allowing it to communicate with
scriptable Mac OS X applications. Other languages can use Apple events as well, but
only AppleScript builds this ability into the very heart of the language itself. That’s how
important application scripting is to AppleScript, and it is very, very good at it.
The second is the exceptionally readable, “English-like” appearance of AppleScript
code. This makes it especially attractive to Mac users who have important tasks that
they’d like to automate, but who don’t have a lot of time to spend learning a more
traditional scripting language. Even if you have never written a single line of program
code, often you can get a good overall idea of what an existing AppleScript will do when
you run it just from looking at it. Take another look at the prepress script I showed you
earlier:
tell application "QuarkXPress 4.01"
tell every page of document 1
set width of (every line box whose width < 0.25) to 0.25
end tell
end tell
Even if you don’t know any AppleScript—or any QuarkXPress, for that matter—you can
probably tell just from reading the preceding script that it’s going to go through a
QuarkXPress document and thicken up any lines that are too thin to print.
Of course, before you can begin writing your own code, you need to learn a bit about
exactly how the AppleScript language works. Still, I think you’ll agree; being able to see
what a piece of AppleScript code does just by looking at it is pretty impressive.
Which brings us to our final concept…
What Is a Script?
A script is a set of instructions for a computer to perform, written in a text-based
language that both humans and computers can understand. Mac OS X includes a
number of popular scripting languages as standard, allowing you to start scripting
straight out of the box. The aim of this book is to teach you how to read and write
scripts using the AppleScript language in particular.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
10
CHAPTER 1: Introducing AppleScript
Every script starts with an idea; for example, “I want to clean up my desktop by moving
everything on it into a folder named after today’s date.” Mind you, having ideas is the
easy bit. The key to writing a successful script is explaining these ideas to AppleScript
using only grammar and vocabulary that it is familiar with, and in sufficient detail that it
knows exactly what you want done. One of the first steps to becoming a skilled
AppleScript user is realizing just how much you must “dumb down” everything you say
to it. If your script does not follow AppleScript’s grammatical rules, AppleScript will not
be able to read it. If your instructions contain words that AppleScript is unfamiliar with, it
won’t know how to carry them out. And if you aren’t precise enough in explaining what
you want done, don’t be surprised if AppleScript gets confused and does something
different from what you intended.
Obviously, if you are completely new to AppleScript, it will take a little while to learn
enough of the language and how to use it to create really interesting and powerful
scripts of your own. Even automating a seemingly simple task such as cleaning up your
desktop will require some bits of knowledge that won’t be fully explained for several
chapters to come. However, it would be a pity to leave this chapter without some sort of
hands-on introduction to the language itself, so let’s start with something really simple:
writing a script to display the traditional programmers’ greeting, “Hello World!”
Your First AppleScript: Hello World!
The first thing you need to start creating your “Hello World!” script is something to
write it in. Open the folder named Utilities in your Mac’s main Applications folder.
You will see several applications within this folder—the one you’re interested in is
AppleScript Editor, which is Apple’s standard tool for creating, viewing, and running
AppleScript code.
NOTE: On Mac OS X 10.5 and earlier, the AppleScript Editor application is named Script Editor
and can be found in /Applications/AppleScript.
Double-click the AppleScript Editor icon to start it up. Upon launching, AppleScript
Editor automatically creates an empty document similar to the one shown in Figure 1–1.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 1: Introducing AppleScript
11
Figure 1–1. An empty AppleScript Editor document
Into this window, type the following line:
display dialog "Hello World!"
At this point, your script is just an ordinary piece of text that could mean anything to
anyone. The first bit of AppleScript magic occurs when you click the Compile button in
the window’s toolbar, so do that now.
Notice anything different? Assuming you typed your text exactly as shown, it should
have changed from purple text displayed in the Courier font to a mixture of blue and
black text set in Verdana. Figure 1–2 shows how the window should look before and
after the Compile button is clicked.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
12
CHAPTER 1: Introducing AppleScript
Figure 1–2. Compiling the “Hello World!” script
What just happened? When you clicked the Compile button, AppleScript Editor asked
AppleScript to read the text you typed and see if it could make sense of it. As you
probably guessed, I didn’t choose the phrase display dialog at random, or wrap the
“Hello World!” message in quote marks without good reason. display dialog is the
name of a command that instructs AppleScript to display a dialog box onscreen. The
quote marks around the phrase “Hello World!” indicate that it is a piece of textual
information. Put these two things together, and you have a script that tells your Mac to
display the text “Hello World!” in a dialog box. Click the Compile button, and
AppleScript checks that your script’s grammar, or syntax, is correct. If it is, AppleScript
translates your text into the precise operations that will be carried out when the script is
run: create an object representing the phrase “Hello World!” and then perform a
command named display dialog using that object. As a final courtesy, AppleScript
gives AppleScript Editor a nicely colored version of your original text that makes it easy
for you to see which bit is which while confirming that it has understood the text that
you’ve typed.
Now that your script is ready to go, all that remains is to run it. To do this, just click the
window’s Run button. Figure 1–3 shows what happens when you do this.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 1: Introducing AppleScript
13
Licensed by
Jim Kilcullen
2884260
Figure 1–3. Running the “Hello World!” script
Congratulations! You’ve now written and run your first successful AppleScript!
Summary
In this chapter, you were introduced to AppleScript and application scripting—what
they’re good for, and a little bit about how they work. In particular, you were introduced
to two key concepts: objects, which are pieces of information, and commands, which
are instructions to manipulate that information.
You also created your first successful script: a traditional “Hello World!” greeting that
combines an object with a command to display the text “Hello World!” in a dialog box
onscreen.
The next chapter maps out these and other key concepts in a bit more detail, providing
you with a bird’s-eye view of AppleScript’s world that will help to prepare you for the indepth coverage of these concepts in Part 2.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
14
CHAPTER 1: Introducing AppleScript
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
15
Chapter
2
AppleScript in Principle
Learning how to script for the first time can be a daunting prospect. Although you do
not need to learn every last feature and technique of scripting to create your own
successful scripts, you do have to know a certain amount of information before you
can really start scripting.
Part 2 of this book will explore each major feature of AppleScript in its own chapter.
Although this approach allows you to study each feature in lots of detail, it has one
obvious disadvantage: until you have read and digested all of those chapters, it is very
difficult to see exactly how all the different pieces of the AppleScript jigsaw puzzle fit
together. Don’t worry, though, because you won’t be going in empty-handed.
The purpose of this chapter is to provide you with a broad map of AppleScript’s world.
Think of it as a tourist guide that briefly describes all the major landmarks you will visit
on your impending trip. Although reading about what each place is like is no substitute
for actually going there, having a rough idea of what to expect means you won’t spend
the entire journey feeling like you have no idea of where you’re off to next or why.
The first two sections of this chapter will help you to make sense of application scripting
and the AppleScript language. The first section breaks down application scripting into
four easy-to-remember “key concepts.” Each key concept is introduced in turn, with a
brief explanation of what it is, what part it plays in the grand scheme of things, and how
it relates to the other key concepts. The second section does the same for the
AppleScript language itself, breaking it down into its four key concepts and introducing
each one in turn. After you’ve been introduced to all eight key concepts, the final section
describes just what it is that makes AppleScript special.
In Chapter 3, you will put this initial knowledge to practical use as you develop your first
serious script. Part 2 of the book will gradually fill in all the gaps.
Enough introduction—let’s get started.
15
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
16
CHAPTER 2: AppleScript in Principle
The Four Key Concepts of Application Scripting
In application scripting, there are four key concepts to understand:
How applications represent information as objects
How applications manipulate objects using commands
How applications organize their objects into object models
How applications describe their objects and commands in dictionaries
Chapter 1 briefly introduced the first two of these concepts, objects and commands, but
they are such an essential part of application scripting that we’ll go over them again,
along with the latter two concepts that have yet to be introduced.
Chapter 5 will fill in all the details that you need to know to script applications for
yourself, and in Part 3 of the book you will put all of this knowledge to work automating
many popular OS X applications.
How Applications Represent Information As Objects
The purpose of most desktop applications is to enable users to work with information. For
example, TextEdit is used to create or view textual data; iTunes is used to manage and
listen to audio data; Adobe Illustrator is used to manipulate graphics data; and so on.
Each of these applications provides a graphical user interface (GUI) to allow human
users to interact with that information. For example, Figure 2–1 shows the main playlist
window from iTunes’ GUI.
As you can see, the playlist window has three main parts: a left-hand sidebar that
displays its playlist data, the main list area where track data can be viewed, and a
toolbar across the top containing buttons for controlling playback.
iTunes also provides a second, invisible interface that allows nonhuman users—
specifically other applications—to view the same data, though in a different way. This
scripting interface represents each piece of data (every playlist, every track, and so forth)
as an object. Although human users cannot view these objects directly, we can observe
them indirectly through scripting languages such as AppleScript (hence the term
“scripting interface”). To demonstrate, open a new window in AppleScript Editor
(/Applications/Utilities/AppleScript Editor.app) and type the following line:
tell application "iTunes" to get the first playlist
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 2: AppleScript in Principle
17
Figure 2–1. iTunes’ main playlist window displaying its data (playlists and tracks)
Now click the Run button to compile and run this script. The script will ask iTunes for its
first playlist object, and iTunes will return a result that looks something like this:
--> library playlist id 414 of source id 41 of application "iTunes"
What you’re seeing here isn’t the actual playlist object—objects that belong to a
particular application only ever exist within that application—but rather a set of
directions, called a reference, that describes how to find that object within iTunes. We’ll
talk about references a bit more in the discussion of the next two key concepts: how
applications manipulate objects and how applications organize their objects.
iTunes’ track and playlist objects also contain lots of useful information about
themselves. For example, if we want to know the name of each playlist, we can ask for it
like this,
tell application "iTunes" to get the name of every playlist
and iTunes will return a list of names like this:
--> {"Library", "Music", "Movies", "Podcasts", "Purchased", "Party Shuffle",
"Genius", "Music Videos", "My Top Rated", "Recently Played", ...}
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
18
CHAPTER 2: AppleScript in Principle
We can ask for lots of other information as well, such as the total playing time (in
seconds) of the “Recently Played” playlist:
tell application "iTunes" to get the duration of playlist "Recently Played"
--> 39066
We can already get this sort of information from iTunes’ GUI, of course, but that
interface has been created specifically for human users and would be very clumsy and
difficult for other applications to use. By providing a second interface that is designed
especially for programs to use, iTunes allows nonhuman users such as AppleScript to
access the same data, but in a format that they find convenient to work with.
Of course, being able to see data isn’t much use if we can’t do anything with it, which
brings us to our second key concept…
How Applications Manipulate Objects Using Commands
Representing data as objects is only one piece of the puzzle. A scriptable application
must also provide nonhuman users such as AppleScript with a way to manipulate that
data. Remember, objects only live within the application that defines them, so we need
some way of telling an application what we want it to do with those objects.
In a GUI, we would use controls such as menus and buttons to perform actions such as
opening a text file in TextEdit, playing a track or playlist in iTunes, or deleting a line in
Illustrator. In application scripting, the feature used to perform an action is called a
command.
Once again, both menus and commands have the same overall goal—to manipulate an
application’s data—but the way each works is specially tailored to suit the type of user
who is using it. For example, to start iTunes playing, a human user would click the “play”
button at the top of iTunes’ playlist window or select the Controls ➤ Play item in iTunes’
menu bar. To start playing iTunes from AppleScript, we send a command named play to
the iTunes application:
tell application "iTunes" to play
Create a new AppleScript Editor document, type this line into it, click the Run button,
and iTunes will begin playing.
So far, so good, but what if we want to tell iTunes to play a particular playlist? A human
user must perform two separate tasks to accomplish this: click the desired playlist to
select it, and then click the Play button to start playing the selection. However, this twostep approach is unnecessary when a script is in control. Instead, many application
commands allow you to specify the object or objects you want them to work with. For
example, iTunes’ play command will let you refer to a track or playlist object
immediately after the command’s name.
Let’s try this now by telling iTunes to play the playlist named “Top 25 Most Played”.
First, here’s how we’ll identify the playlist we’re interested in:
playlist "Top 25 Most Played"
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 2: AppleScript in Principle
19
This is a reference, albeit a simple one, that identifies the playlist object we’re interested
in by its name (the part within the double quotes).
Next, write this reference after the play command in your earlier script:
tell application "iTunes" to play playlist "Top 25 Most Played"
Finally, click the Run button to compile the script and run it. iTunes will immediately
begin playing the tracks in your Top 25 playlist.
NOTE: The “Top 25 Most Played” playlist is one of the standard playlists in iTunes, although the
name may vary on non-English systems. If your Top 25 playlist is named differently, just change
the playlist name used in the preceding script to match the playlist name shown in iTunes’ GUI.
How Applications Organize Their Objects into Object
Models
So far we have looked at how an application’s scripting interface represents individual
pieces of data to its nonhuman users as objects, and how it allows those users to
manipulate that data by sending commands to the application. For our third key
concept, let’s take a look at how scriptable applications organize their objects.
Many users have to deal with large quantities of different kinds of data, so to make all that
data manageable, applications need to organize it somehow. For example, a typical
iTunes user may own thousands, or even tens of thousands, of music tracks in their
library. An easy way to organize this library is to collect related tracks together—for
example, all the tracks by a particular artist, all the tracks that fit a romantic mood, and so
on—and put each set of tracks in a playlist of their own. Figure 2–2 shows a collection of
tracks gathered together in a single user-defined playlist, as seen in iTunes’
GUI.\Remember that a lot of the information we see in iTunes’ GUI can also be seen in
its scripting interface. How the GUI represents information to its human users may or
may not resemble the way that the scripting interface represents the same information
to its software-based users, of course. In this case, though, the similarities are actually
very strong.
Just as the GUI shows tracks as being contained by a playlist, so does the scripting
interface represent track objects as being contained by a playlist object. The diagram
in Figure 2–3 illustrates how this containment structure appears from AppleScript’s
point of view.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
20
CHAPTER 2: AppleScript in Principle
Figure 2–2. iTunes’ main playlist window displaying a number of tracks collected together in a user-defined
playlist
Figure 2–3. A diagram showing how several track objects can be contained by a playlist object
This ability of a playlist object to contain track objects is just part of a larger containment
structure: in turn, playlist objects are contained by other objects called sources, and all
these source objects are contained by a single application object. This entire structure
is what’s known as an object model. Almost every scriptable application has an object
model, and the way that an application’s object model is laid out is unique to that
application.
Organizing objects into object models makes them easier to manage, particularly in
applications such as iTunes that can easily contain many tens of thousands of objects.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 2: AppleScript in Principle
21
Figure 2–4 shows a simplified example of a typical iTunes object model (I’ve omitted
some less important parts of the object model and cut down the number of tracks
shown for sake of space). This should give you some idea of what AppleScript can see
when it talks to iTunes’ scripting interface.
Figure 2–4. A diagram showing how a typical iTunes object model might look (simplified for space)
Of course, now that iTunes has nested all of its track objects within playlist objects, and
all of its playlist objects within source objects, and all of its source objects within its
main application object, scripting interface users such as AppleScript will need some
way of locating objects within this structure.
This is where references come in, providing directions through the object model to the
objects you want to use. For example, the following reference identifies the first track
object of the first playlist object of the first source object:
tell application "iTunes"
track 1 of playlist 1 of source 1
end tell
How Applications Describe Their Objects and Commands in
Dictionaries
Having learned about objects, commands, and object models, you probably are
wondering how on earth you are supposed to determine what kinds of objects and
commands a scriptable application provides, and how those objects are organized into
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
22
CHAPTER 2: AppleScript in Principle
an object model. The answer to this question is simple: every scriptable application
contains its own built-in documentation, called a dictionary, that lists all the commands
that are available to use and describes each different kind, or class, of object you will
find within the application’s object model.
We have a lot more information to get through in this chapter, including the four key
concepts of the AppleScript language, so we’ll resume the examination of dictionaries
in Chapter 5, which discusses all the concepts behind application scripting in a lot
more detail. In the meantime, Figure 2–5 shows part of iTunes’ dictionary to give you a
rough idea of what a typical application dictionary looks like when viewed in
AppleScript Editor.
Figure 2–5. Part of iTunes’ built-in dictionary, displayed in AppleScript Editor’s dictionary viewer
The Four Key Concepts of the AppleScript Language
Now that you are familiar with the four key concepts behind application scripting in
general, let’s proceed to the four key concepts behind the AppleScript language itself:
How AppleScript represents information as objects
How AppleScript manipulates objects using commands, operators,
and variables
How AppleScript makes decisions on what to do and when to do it
How AppleScript organizes code using handlers and script objects
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 2: AppleScript in Principle
23
Although this section is not very long, it is important—in Part 2 of the book we will spend
a great deal of time exploring the many pieces that make up the AppleScript language,
so it’s a good idea to know beforehand how and where each of those pieces is
supposed to fit in the overall picture.
Let’s get started.
How AppleScript Represents Information As Objects
Like scriptable applications, a big part of AppleScript’s job is to manipulate information,
so it probably won’t surprise you to hear that AppleScript can create and work with
objects of its own. Although AppleScript objects, like application objects, are used to
represent information, there are a few differences in how they behave.
Licensed by
Jim Kilcullen
2884260
The first difference is that AppleScript objects are much simpler than application
objects. Application objects normally represent quite specialized pieces of information:
windows and documents in TextEdit, playlists and tracks in iTunes, paths and layers in
Illustrator, and so forth. AppleScript objects represent the most basic building blocks
you can use in your scripts: simple things like numbers, pieces of plain text (called
strings), and dates. Here are some examples as you would write them in your scripts:
42
3.14
"Hello World!"
date "Sunday, May 17, 2009 12:41:13 PM"
Some types of AppleScript objects are a little fancier in that they can contain other
objects. For example, here’s a list object containing my weekly lottery numbers:
{2, 3, 17, 18, 43, 45}
The second difference is that AppleScript objects, unlike application objects, don’t live
in an organized object model. Instead, AppleScript objects can exist independently
within a running script, appearing anywhere they like. Don’t worry though if this sounds
a bit unruly: AppleScript provides its own set of features for keeping objects well
organized—more on this in the next section.
The third difference between AppleScript objects and application objects is that
because AppleScript objects are not tied to any single application, they can be used
anywhere. For example, in the earlier “How Applications Represent Information As
Objects” section, you saw how to ask iTunes for the names of its playlists:
tell application "iTunes" to get the name of every playlist
--> {"Library", "Music", "Movies", "Podcasts", "Purchased", "Party Shuffle",
"Genius", "Music Videos", "My Top Rated", "Recently Played", ...}
As you can see, iTunes returns an AppleScript object—specifically a list object
containing several string objects. We can now manipulate these objects directly in
AppleScript or use them in other application commands.
Chapters 6 to 10 will present the various types of objects available in AppleScript, and
you will find them used throughout the book.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
24
CHAPTER 2: AppleScript in Principle
How AppleScript Manipulates Objects Using Commands,
Operators, and Variables
Not only can AppleScript represent information as objects, it allows you to manage and
manipulate those objects too. AppleScript provides three important features for working
with objects: commands, operators, and variables.
Using Commands
You already met commands in the earlier discussion of how to manipulate application
objects. Well, AppleScript provides various commands of its own too, and even allows
users to define their own commands. For example, AppleScript’s built-in count
command allows you to count the number of characters in a string object,
count "Hello World!"
--> 12
or the number of items in a list object:
count {2, 3, 17, 18, 43, 45}
--> 6
Using Operators
Operators are similar to commands in that they are also used to manipulate objects.
Unlike commands, however, operators have their own syntax and you cannot define
new operators of your own—you can only use the operators that are already built into
AppleScript itself.
AppleScript has 25 operators in total. These include math operators that allow you to
perform simple math calculations on numerical objects, comparison operators that let
you compare two objects to see if they are the same or different, and a very handy
“concatenation” operator that you can use to join two strings or two lists together. Here
are several examples to give you an idea of how operators are used:
1 + 2
--> 3
16 / 2.5
--> 4.0
"HELLO" is equal to "hello"
--> true
99 < 3.5
--> false
"Hello " & "World!"
--> "Hello World!"
{2, 3, 17, 18, 43, 45} & {6}
--> {2, 3, 17, 18, 43, 45, 6}
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 2: AppleScript in Principle
25
Using Variables
Unlike commands and operators, which are used to manipulate objects, variables are
what we use to store objects when we aren’t working with them.
Think of a variable as a box. Whenever a script has an object that it will need to use
again later, it can put it in this box for safe storage while it goes off and does other
things. Later on, when it needs to use that object again, it can retrieve it just by finding
the box it put it in earlier. To make these storage boxes easy to identify, each one has its
own name, or identifier.
For example, the following line of code defines a list object containing my lottery
numbers and assigns (puts) it in a variable (box) named “lucky_numbers”:
set lucky_numbers to {2, 3, 17, 18, 43, 45}
Later on, if I want to use this list object again, I can retrieve it by referring to my
lucky_numbers variable:
lucky_numbers
--> {2, 3, 17, 18, 43, 45}
Best of all, we can combine all of these features together. For example, if I want to
check that I have exactly six numbers in my lucky number list, I can do so as follows:
(count lucky_numbers) is equal to 6
--> true
I will discuss all of these features—commands, operators, and variables—in a lot more
detail in Part 2 of the book.
How AppleScript Makes Decisions on What to Do and When
to Do It
The third key concept in AppleScript is that running scripts have the ability to decide
what they should do and when they should do it. Roughly speaking, a script may face
three kinds of questions when manipulating data:
Should I do this?
How often should I do that?
What should I do if things go wrong?
Happily, AppleScript provides several valuable features for dealing with each one of
these questions.
Conditional statements allow a script to decide if an action should be taken. A
conditional statement always starts with the word if at the beginning of a line and
normally ends with the words end if on a later line. Here is an example:
if 2 + 2 is equal to 4 then
display dialog "Two plus two is four."
end if
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
26
CHAPTER 2: AppleScript in Principle
Repeat statements allow a script to control the number of times the action is performed.
A repeat statement always starts with the word repeat at the beginning of a line and
ends with the words end repeat on a later line. Here is an example:
repeat 15 times
display dialog "Hello again!"
end repeat
Finally, try statements allow a script to catch and clean up the mess caused when an
action unexpectedly (or expectedly) backfires. A try statement always starts with the
word try at the beginning of a line and ends with the words end try on a later line. Here
is an example:
try
3 / 0
on error
display alert "Oops! Can't divide by zero."
end try
We’re not going to explore how these features work now—we’ll do that in Chapters 14
and 15. However, it is useful to know the purpose of each and be able to recognize them
when you see them, as they are used in example scripts throughout this book.
How AppleScript Organizes Code Using Handlers and Script
Objects
The first three key concepts in AppleScript—representing data, manipulating data, and
making decisions—all share a common purpose: to make your scripts do things. The
final key concept is different: instead, it is concerned with how you organize the code
that goes into your scripts.
Why should your code be organized?
Well, the first bit of news is that if you write only small utility scripts, your code usually
doesn’t need much, if any, organization to solve your problems successfully. Also, when
you’re beginning to learn how to script, you’ll have more than enough to do just learning
the basic features needed to do anything at all. For these sorts of simple scripts, you
just start typing at the beginning of the script and keep on going until you reach the end.
As long as the completed script compiles and runs and is easy to test and debug, this is
the easiest way to get the result you want.
The second bit of news is that once you have mastered the basics, you will probably
want to create more powerful and ambitious scripts. This is where good organizational
skills become increasingly important, because the real trick to developing medium- to
large-scale scripts successfully isn’t writing the code, but rather preventing that code
from growing so knotty and complicated that it becomes impossible to understand.
Chaotic code is extremely difficult to test and debug effectively, or to modify later if you
need to add new features. Any time you change one part of the code, it’s all too easy to
break other parts without even realizing it—too many pieces are entangled with too
many other pieces for you to keep track of them all.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 2: AppleScript in Principle
27
Obviously, what larger scripts need is a bit of discipline. The trick here is to break down
large, complicated tasks into several smaller, simpler pieces that are easier to
understand and manage. This approach requires two things: good design skills—which
you can learn with time and practice—and language features.
We will discuss good design techniques in later chapters, after you have had a chance
to familiarize yourself with the basic tools of the trade—that is, the features provided by
the AppleScript language. When it comes to organizing your code, AppleScript provides
two features that you can use: handlers and script objects.
Script objects are a particularly powerful feature that are not needed for most tasks in
AppleScript, so I won’t say anything further about them here. More advanced scripters
can learn about them in Chapter 19.
Handlers are a simpler feature that many scripters find increasingly useful once their
scripts grow beyond one or two dozen lines of code. Using script handlers allows you to
define your own commands using only AppleScript code. That’s right—not only can you
use the thousands of existing commands provided by scriptable applications, you can
create your own commands too, custom-tailored to your exact needs!
Even if you only write short and simple scripts that don’t require a highly structured
design, you may find that using handlers is a useful way to package some commonly
used pieces of code. For example, you can package the code to find and replace a
piece of text within a string as a handler named find_and_replace. Then, any time you
write a script that needs to perform a find and replace operation, just paste your
find_and_replace handler into your script somewhere and send a find_and_replace
command each time you want to use it.
Many of the longer examples in this book use handlers to define these sorts of simple
convenience commands. Several go one step further and use handlers to organize their
overall structure, breaking a long, complex task down into several smaller, simpler
sections that are easier to test, modify, and understand. You can easily identify these
handlers because the first line of the handler always begins with the word on or to,
followed by the handler’s name. The last line of the handler consists of the word end
followed by the handler’s name again. Between these two lines is the code that will run
when the handler is called.
Here is a very simple example of a handler called square_root that takes a number,
calculates its square root, and returns it:
on square_root(the_number)
return the_number ^ 0.5
end square_root
And here is an example of a square_root command that uses this handler to calculate
the square root of 25:
square_root(25)
--> 5.0
Looking at the preceding handler, you may be wondering exactly how the calculation
part works—after all, doing math in AppleScript won’t be covered until Chapter 8.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
28
CHAPTER 2: AppleScript in Principle
However, this brings us back to one of the great benefits of using handlers: as long as
you know that the handler named square_root calculates the square root of a number,
you don’t actually need to know how it does it. Just call it, and it does all the work for
you. It’s that simple!
Tying It All Together: What Makes AppleScript
Special
Now that you’ve had a general tour of AppleScript, let’s finish off with a brief look at its
most distinctive characteristics—or what makes AppleScript “AppleScript.”
The English-like Syntax
Some people love it. Some people hate it. Almost everyone will agree: it’s certainly
different! Yes, I’m talking about AppleScript’s famously “English-like” appearance.
What’s so special about it? Well, AppleScript’s word-based syntax makes it amazingly
easy for an ordinary Mac user to look at a piece of AppleScript code and get a pretty
clear idea of what that code will do when it is run…even if she doesn’t know any
AppleScript herself. This makes AppleScript unusually quick to get started in, as the first
step of learning any new language is figuring out how to read it.
The downside of AppleScript grammar is that it gives you very few clues as to how
precisely the script will carry out a particular task. For example, if you see the word
count in a script, is that the name of a command, a variable, or some other feature?
What about count lines—is that a single name, “count lines,” or two separate names,
“count” and “lines”? Figuring out these sorts of fine technical details for yourself can
take some time and effort, particularly if you have to search through application and
scripting addition dictionaries to find the information you need to interpret the code
correctly.
More traditional scripting languages typically use various symbols—dots, curly braces,
parentheses, and so on—to indicate exactly what type of structure you are looking at;
for example, count(lines) would be a command, count, that takes an object stored in a
variable named lines. Traditional languages also avoid using spaces within keywords;
for example, count_lines would clearly be a single name. The downside of this sort of
traditional scripting language syntax is that until you’ve learned exactly what all these
squiggles and signs actually mean, the entire script will appear completely cryptic and
you won’t be able to tell what it does at all.
In other words, all scripting languages make trade-offs in their choice of syntax.
AppleScript’s trade-off is that in order to write scripts for yourself, you need to have a
good grasp of the various vocabularies used by scriptable applications and AppleScript
itself. On the other hand, a well-written AppleScript can be wonderfully elegant and easy
to read when you want to find out what the script does—and it is this readability that
makes AppleScript so attractive and approachable to many Mac users who might
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 2: AppleScript in Principle
29
otherwise dismiss scripting as something that’s intended for “professional”
programmers only.
Built-in Application Scripting Support
Scripting applications is such a huge part of what AppleScript does that it can be easy
to forget that the AppleScript language and a scriptable application are actually two very
different things. The ease with which we can forget about those differences and just get
on and do things is largely due to the almost seamless integration of the AppleScript
language with the Apple event technology that applications can use to communicate
with one another.
While other languages can also use Apple events through external add-ons, AppleScript
is almost unique in having this ability built directly into the language itself. This makes it
very convenient to use, as application scripting in AppleScript “just works” straight out
of the box. It also allows the language to integrate application-defined keywords directly
into the user’s code, giving scripts their distinctive English-like appearance.
If the merging of these two technologies has a downside, it’s that sometimes it can be a
little tricky to tell if the objects and commands you’re working with belong to AppleScript
itself or to one of the applications that the script is controlling. Often this difference isn’t
really important: AppleScript-defined objects have many similarities with applicationdefined objects, and both behave in much the same way in a lot of situations.
Sometimes, though, the differences are big enough that they can catch you unawares
when you expect an object to behave one way only for it to do something else instead,
like cause an error.
One of the tricks to mastering AppleScript is knowing what the similarities and
differences are between application objects and AppleScript objects, and being able to
tell which kind of object you’re dealing with at any point in your script. With the help of
this book and plenty of practice, this is something you will get good at in time, and your
scripts will become more elegant and reliable as a result.
Attaching Scripts to Applications
Attachability is the ability to hook, or “attach,” a script to a desktop application so that the
script can be triggered by the application itself. This can be tremendously useful when you
need a script to run automatically: just attach it to an application, and when the application
does whatever it is you’re interested in, it will let your script know about it.
Unfortunately, while external scripting interfaces are common among Mac applications,
support for attachability is much less widespread. Even applications that do allow you to
attach scripts often only provide notifications of one or two types of events, which may
or may not be the ones that you’re actually interested in.
Still, attachability is supported in quite a few areas and can be used for a variety of
tasks. Here are a few examples:
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
30
CHAPTER 2: AppleScript in Principle
System Events (a hidden utility application included in Mac OS X that
provides many useful AppleScript-related features) can attach scripts
to folders in the file system. A Folder Action script will be triggered
when files are added to, or removed from, the folder it is attached to.
For example, you might create a drop folder named Upload to
Website on your desktop that automatically zips and uploads any files
that are dragged and dropped onto it.
Apple’s Mail application can attach scripts as e-mail rules so that they
are triggered when an e-mail message arrives, allowing the script to
process that message automatically. For example, the script might
scan the message content for the time and location of a weekly
meeting and then create an entry in iCal for that meeting.
AppleScript Editor can attach scripts to its context menu, allowing you
to run them with a right-click. AppleScript Editor already includes a
number of handy context menu scripts for inserting commonly used
chunks of code into your script document, and you can easily add
more.
While most of the example scripts provided in this book are designed to run directly
from AppleScript Editor, later chapters include several attachability-based examples.
You can also try modifying some of the stand-alone examples to make them work as
folder actions.
NOTE: You may sometimes hear the term Open Scripting Architecture, or OSA, used in
discussions of AppleScript. This is the plug-in system that attachable applications use to load the
AppleScript language plug-in so that they can run scripts written in AppleScript. In theory, other
scripting languages can also be packaged up as OSA components, but to date AppleScript is the
only language that provides full OSA support.
The AppleScript Community
Throughout this chapter I’ve described the key features and concepts that make up
scriptable applications and AppleScript. To finish, I’d like to mention one last “feature” of
AppleScript: the many people who support and use it. AppleScript has been on the go
for more than a decade and a half now, and in that time an enthusiastic and supportive
community of developers and users has built up around it.
Within the AppleScript community you will find all sorts of people from many different
walks of life: from teenage hobbyists with a pressing need to tidy their vast iTunes music
collections, to full-time workflow developers creating powerful automation systems for
the publishing industry; from the Mac users who had never written a line of code before,
to the professional software developers who produce the scriptable applications that
make AppleScript the success it is today.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 2: AppleScript in Principle
31
Many members of the AppleScript community have worked with the language for years,
building up considerable knowledge of both the AppleScript language and the many
different applications it can be used to control—information and experience that they are
only too happy to share with others.
So whether it’s a trip to Apple’s AppleScript Users mailing list to pop a quick question,
or a shopping trip around MacScripter.net’s huge collection of third-party scripts for a
ready-made solution or something to pull apart and learn from, the AppleScript
community is there to help you. And perhaps one day soon, as a skilled AppleScripter
yourself, you might do the same for others.
TIP: The introduction to this book includes links to many useful AppleScript resources, including
community web sites, mailing lists, and discussion boards.
Summary
This chapter has provided a quick tour of all the major landmarks in the world of
AppleScript and application scripting, telling you what they are and showing where they
fit in the overall picture.
The first section introduced the four key concepts behind application scripting: how
applications represent information as objects, how these objects can be manipulated by
commands, how objects are assembled into object models to make them easier to
manage, and how all these structures are described in dictionaries.
The second section introduced the four key concepts behind the AppleScript language
itself: how AppleScript also represents information as objects; how these objects can be
manipulated and managed using commands, operators, and variables; how scripts can
make decisions on what to do and when; and the advanced features that AppleScript
provides for organizing code in larger, more complex projects.
Part 2 of this book will cover all these features in exhaustive detail. Before you get to
that, however, you’ll have some fun in the next chapter as you write your first “real”
AppleScript.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
32
CHAPTER 2: AppleScript in Principle
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
33
Chapter
3
AppleScript in Practice
Licensed by
Jim Kilcullen
2884260
Now that you have a general idea of what makes AppleScript and application scripting
tick, it’s time to roll up your sleeves and create your first serious AppleScript.
As a heavy-duty Mac user, I frequently drop interesting-looking web links, text clippings,
zip files, and so forth onto my desktop “to put away later.” Of course, what actually
happens is that I never do get around to filing them away myself; instead, my desktop
turns into such a mess that in the end I make myself a new “desktop archive” folder and
throw everything into that. Although I might never get around to organizing these files
properly, my desktop is nice and clean again—at least until I start accumulating a fresh
pile of random files.
Given how bad I am at doing my own housekeeping, wouldn’t it be much more
convenient if my Mac could take care of this tedious task for me? Well, with
AppleScript’s help, it can!
The Project: Tidy Desktop
In this project, we’ll create a simple yet useful housekeeping script that cleans up your
desktop by moving any files that are on it into a newly created “desktop archive” folder.
Along the way, we’ll also explore some of the basics of AppleScript grammar, and try
out some of the concepts discussed in Chapter 2.
Before we begin, however, I’m going to show you the finished script itself:
set date_string to date string of (current date)
set folder_name to "Desktop Archive for " & date_string
tell application "Finder"
set archive_folder to make new folder at home ¬
with properties {name:folder_name}
move every file of desktop to archive_folder
end tell
Presenting the completed code up front may seem a little like cheating—however, this
book isn’t a homework exercise, and the aim of this project isn’t simply to create a
33
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
34
CHAPTER 3: AppleScript in Practice
finished script. Instead, the real goal is to help you understand how you, as a scripter,
can get from an initial idea to a successful working product.
So now that you know what the finished script looks like, you can focus on the entire
journey without having to wonder what the destination might be. Enjoy the ride!
TIP: Don’t get stressed if you find the rest of this section too much to take in at first. Just go
with the flow, read the text, and do the exercises. All the points covered here will be repeated in
great detail throughout the book.
Planning the Script
The goal of this script is to move all the files from the desktop into a newly created
“archive” folder. The folder’s name should include the date on which the folder is
created, so that users know when the items the folder contains were moved there.
Now that we know what the script should do, we can break down the process into
individual steps. This is a pretty simple project, with three steps in total:
1.
Create the folder name, which will look something like “Desktop Archive
for Friday, January 8, 2010”.
2.
Create a new folder with this name. To keep things simple, we’ll create
the folder in the current user’s home folder.
3.
Move all the files that are currently on the desktop into this new folder.
Having identified each of the steps involved, we can figure out what sort of features we
need to perform each task:
For the first step, we need some way to get today’s date as a piece of
text (for example, “Friday, January 8, 2010”). AppleScript provides all
the features we need to obtain this information, as you’ll see later in
the chapter.
For the second and third steps, we need to manipulate the file system.
The Finder provides excellent AppleScript support, making it the ideal
tool to use here.
We need some way to assemble the full file name by joining the
“Desktop Archive for ” text with the date text. For this job, we use
AppleScript’s concatenation operator (&).
We need some way to store the various pieces of information that our
script creates and uses. AppleScript variables fit the bill perfectly.
Okay, that’s our plan of action. Let’s start turning it into actual code.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 3: AppleScript in Practice
35
Writing the Script
Whereas our plan identifies three steps in total, I will cover the development of the script
in two main sections: one covering the AppleScript-only part of the script (step one), the
other covering the Finder automation part (steps two and three).
As we work through this project, I will also go over some of AppleScript’s basic syntax
(grammar) rules—these appear as sidebars within the main project description. Although
reading about AppleScript grammar isn’t nearly as interesting as developing the project
itself, it’s a good idea for you to get familiar with the basic constructs and jargon now so
that you can more easily follow the discussion of the example scripts that are presented
later in the book.
Creating the Folder Name
The aim of this step is to create a name for our new archive folder. Obviously, you need
somewhere to write this script, so start up AppleScript Editor if it isn’t already running
(/Applications/Utilities/AppleScript Editor.app) and choose File ➤ New to create a
new script document.
The process of creating the folder name is actually made up of two smaller steps. The
first part is to get the current date as a piece of text. The second part is to join the date
text with the other half of the folder name, “Desktop Archive for ”.
Getting Today’s Date As Text
To get today’s date, type the following code into AppleScript Editor:
current date
As you might guess, current date is the command that returns the current date and
time when it is run. In fact, run it now. Just click the Run button at the top of the script
window, and AppleScript Editor will compile and run this command, and display the
result at the bottom of the window. Figure 3–1 shows a typical result.
Did you notice that the text you typed was initially formatted as purple Courier? This
formatting indicates code that has not yet been compiled. When you clicked the Run
button, AppleScript Editor asked AppleScript to compile your code and then run it.
Compiling the script is an essential step before running it: among other things,
AppleScript checks whether or not your script’s syntax (grammar) is correct.
TIP: You can check your script’s syntax at any time by clicking the Compile button. This
compiles the script but doesn’t run it. It’s a good idea to compile your script frequently as you
write it so that you can quickly identify and correct any syntax problems that occur.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
36
CHAPTER 3: AppleScript in Practice
Figure 3–1. The result of running the current date command in AppleScript Editor
After you successfully compile the script, the font and the color of the text both change.
Suddenly, AppleScript understands what you’re saying…although whether or not it
knows how to do what your script is telling it to do is a different question—one that’s
answered only when you actually run the script.
Now that we have a date object representing the current date and time, the next task is
to obtain the date part as a string object.
NOTE: This book talks a lot about “strings.” “String” is the traditional computing jargon for a
text-based object, as in “a string of characters.” In Mac OS X 10.4 and earlier, string was also
the name of one several different types of text objects used by older versions of AppleScript.
When AppleScript 2.0 was introduced in Mac OS X 10.5, it greatly simplified things by
introducing a single, one-size-fits-all text type. It also created a bit of confusion by naming this
new type text instead of the more familiar string. Chapter 7 discusses this topic in much
more detail; for now, just regard the terms “text” and “string” as interchangeable.
As discussed in Chapter 2, many objects contain extra pieces of information about
themselves, and AppleScript objects are no exception. Date objects, for example, allow
you to extract individual pieces of information: the year, the name of the month, the day
of the month, the number of seconds that have passed since midnight, and so on.
For this exercise, the data we want is stored as a property of the date object. This
property is called date string, and to get its value we use a reference:
date string of (current date)
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 3: AppleScript in Practice
37
Type this into your script window and run it, and you will get a result similar to the
following:
"Friday, January 8, 2010"
This is our string object. You can tell it’s a string object because AppleScript displays it
as a piece of text enclosed in a pair of straight double quotes. More on strings in a
moment.
You may notice a couple of other things about our growing script. The first point of
interest is the use of the word of—well, we’re asking for a property of an object, so it’s
only natural that AppleScript should have an of keyword especially for constructing this
reference. I will discuss references in great detail in Part 2 of this book, so I’ll skip the
rest of the details for now.
The second thing you’ll notice is that we put parentheses around our original current
date command. Although AppleScript is pretty good at making sense of the code you
write, there are times when it needs a little extra help in deciding which bits are which.
By adding parentheses, we make it clear to AppleScript that it should treat current date
in a particular way when compiling the script.
ABOUT APPLESCRIPT GRAMMAR: EXPRESSIONS
Let’s try an experiment. Delete the opening and closing parentheses for a moment, and try compiling the
script without them:
date string of current date
Alas, when you click Compile this time, an syntax error occurs: “Expected expression but found command
name.” What on earth does that error message mean? Well, you already have some idea of what a
command is: it’s a type of instruction you can send to scriptable applications and AppleScript—in this
case, the current date command.
What’s an expression? Well, in AppleScript grammar, an expression is any piece of code that returns an
object when evaluated. For example, "Hello World!" is an expression. So is 2. More complex
expressions can be constructed using operators; for example, 2 + 2 is equal to 4.
I’ll talk more about expressions in later chapters; for now, the point I want to make is that commands,
weirdly enough, aren’t considered to be expressions. The reason for this is simple: although most
commands do return an object, they aren’t required to do so, and some don’t. As a result, when we try to
use a command in a place where AppleScript expects an expression—in a reference, for example—we
get a syntax error instead.
Fortunately, you can clarify your intentions (“yes, I really do mean to use a command there”) by wrapping
your command in parentheses. Not only does this tell AppleScript that it should treat that particular piece
of code as a single unit within the larger script, a pair of parentheses is also considered to be an
expression itself, so AppleScript is happy once again.
Inconsistencies such as this make AppleScript grammar a bit more tricky to learn than it ought to be, but,
hey, no language is perfect. With time and practice, however, you will get used to it—quirks and all.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
38
CHAPTER 3: AppleScript in Practice
Now that we have our string object, we should probably store it somewhere for safe
keeping. For this, we use a variable. Let’s call this variable date_string—not very
imaginative, I know, but we only need it for a short time, so there’s no need to get fancy.
(In later chapters I’ll discuss good naming practices for your own variables.)
To assign an object to a variable, we use AppleScript’s built-in set command. Here’s
how our code should now look:
set date_string to date string of (current date)
Our date string of (current date) expression goes on the right side, after the
keyword to (which is a part of the set command). Our variable name, date_string,
appears after the keyword set. Now when AppleScript evaluates the expression, the
object it returns is stored safely in the date_string variable. Later on, our script can
retrieve this object again when it needs to use it for something.
Okay, so the first line of our script is done. Compile it, run it, and make sure that it
works. If all goes well, you should see the string object appear in the bottom half of the
script window. If not, check your code carefully, fix any mistakes, and try again until it
does work.
Putting the Name Together
Let’s pick up the pace a little now. We have the second half of our file name, but we still
need the first half. Begin the second line of the script by typing the following:
"Desktop Archive for "
Take care to use straight double quotes, not single or curly ones, and be sure to put a
space after the word for exactly as shown.
ABOUT APPLESCRIPT GRAMMAR: LITERALS
Let’s take a closer look at what we’ve just written:
"Desktop Archive for "
In grammatical terms, this is called a literal; in this case, a literal string object. Why “literal”? Because it’s
how we [literally] write an AppleScript object as AppleScript code. A string literal, for example, consists of
the actual text wrapped in a pair of double quotes. Other types of objects have different literal
representations: a literal number object is written as, well, a number; a literal list object is indicated by a
pair of curly braces; and so on.
Literals are also considered to be expressions, which means that when AppleScript evaluates our literal
string, it will create a string object that contains the text that we wrote inside the quotes.
We can now join this string object with the other string we stored earlier in the
date_string variable. To do this, we use my own personal favorite AppleScript operator:
the concatenation operator. This is written as an ampersand (&) symbol with one object
on the left and the other on the right. Here’s how our second line looks when we put
these pieces together:
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 3: AppleScript in Practice
39
"Desktop Archive for " & date_string
Finally, because we’re being especially tidy in this project, we can assign the result of
this new expression to another variable, this time called folder_name. Here’s how our
script now looks:
set date_string to date string of (current date)
set folder_name to "Desktop Archive for " & date_string
Compile it, run it, and check that it gives the proper result, which should look something
like the output shown in Figure 3–2.
Figure 3–2. The result of running the first two completed lines of the script
In particular, did you remember to insert a space between for and the day of the week?
Remember, AppleScript does exactly what you tell it do, so if you don’t put a space
between the two parts of our file name, the two words will run together as
“…forWednesday…” when AppleScript joins them together.
Once you’re satisfied that everything is working correctly, it’s time to move on to the
next step: creating the archive folder.
Interacting with the File System
Now that we have the name for our new desktop archive folder, we are ready to create
the folder and move the contents of our desktop into it.
The AppleScript language itself does not include any features for working with the file
system, so we need to look for another way to do this. As I’ve already discussed,
AppleScript’s greatest feature is its ability to control “scriptable” Mac applications, so
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
40
CHAPTER 3: AppleScript in Practice
the answer is to look for an application that knows how to work with the file system and
provides some sort of scripting interface.
In fact, Mac OS X provides us with several options we could use, such as the hidden
System Event application that provides a wide range of useful features for AppleScript
to use, or perhaps the Unix command-line tools that live further down in the operating
system. There are even some third-party file managers available that include AppleScript
support, such as Cocoatech’s Path Finder.
For this project, however, we will go with the most obvious solution, Mac OS X’s Finder
application. Finder has a well-designed scripting interface that is elegant and (once you
know a bit of AppleScript) straightforward to use.
We will explore the Finder’s scripting interface in much more detail in later chapters, so
for now I will only cover the essential points that you need to know to get this project up
and running. Let’s start by looking at how we tell AppleScript that we’d like to talk to the
Finder.
CAUTION: Application scripting interfaces, unlike GUIs, do not come with an Undo feature! When
manipulating the file system (or doing anything else with AppleScript that might affect important
files or work), make sure you have sufficient backups prepared in case anything goes wrong. If
you run a script and it destroys your files, either by design or by accident (for example, due to a
bug), the last thing you want is to lose that information forever!
Addressing the Finder
In Chapter 2, you learned that the way to make scriptable applications do things is to
send them commands. Before writing our commands, however, we need to tell
AppleScript where to send them. In this case we want to send them to the Finder, so the
first step is to identify the Finder application in our script. Here is the code for doing this:
application "Finder"
This structure is what’s known as an object specifier, because it is used to identify, or
specify, an object of some sort. Object specifiers are mostly used when identifying
objects that live within other objects; however, AppleScript also uses them to create
several types of AppleScript objects from scratch, such as date, file, and—as seen
here—application objects.
ABOUT APPLESCRIPT GRAMMAR: OBJECT SPECIFIERS
Object specifiers can be a rather tricky concept to wrap your head around at first, so before we go any
further, let’s spend a little time getting acquainted.
Here is our object specifier from a moment ago:
application "Finder"
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 3: AppleScript in Practice
41
You saw another example of an object specifier earlier in the chapter when we ran the current date
command; in that case, AppleScript Editor displayed the resulting date object as an object specifier that
looked similar to this:
date "Friday, January 8, 2010 1:41:32 PM"
What is the point of an object specifier? Well, as you’ve already seen, AppleScript provides special literal
syntax for creating several basic types of objects: a numerical object is written as one or more digits, a
string object is written as the text itself surrounded by double quotes, and so on.
However, many other types of objects do not have a custom syntax in AppleScript, so we need a more
general way of creating or identifying those objects. The solution here is to use an object specifier, which
is written as the type, or class, of the object we want, followed by an object of some sort.
If the object being specified is an AppleScript object, AppleScript creates that object from scratch. If it is an
object in a scriptable application, AppleScript creates a reference to that object. In either case, the second
part of the object specifier—the object part—provides AppleScript with all the information it needs to
create or identify the object we want. For example, a date specifier takes a string object describing the
date and time we want the newly created date object to have. For our application specifier, we use a
string object containing the name of the application we’re interested in, which in this case is the Finder.
One last thing: if you type in the following line and run it,
application "Finder"
the result will also appear as:
application "Finder"
When displaying an object back to the user, AppleScript generally uses the same syntax that you would
use yourself when typing in that object as a literal in your script. This makes it really easy for you to see
exactly what sort of object was returned. (There are one or two exceptions to this rule—for example,
POSIX file specifiers are written one way but displayed another—but we’ll deal with those quirks when
we get to them.)
Now that we have an application object that identifies the application we want to
control, we need some way to direct our commands at it. Once again, AppleScript
provides us with a language feature for exactly this task: the tell statement. Here is the
syntax for AppleScript’s tell statement:
tell target_object
end tell
A tell statement (or “tell block”) controls where commands are sent. Normally when
AppleScript executes a command in a script, it sends the command to the script itself. If
the script knows how to handle that particular command, then great—AppleScript lets
the script handle it. On the other hand, if the script doesn’t recognize the command,
AppleScript then sends the command to the application running the script. If the
application doesn’t understand the command either, AppleScript gives up and reports
an error.
Although this process is great if you want to send a command to your script, or to the
application running the script (in this case, AppleScript Editor), it isn’t useful if you want
to send the command to some other application, such as the Finder. To send our
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
42
CHAPTER 3: AppleScript in Practice
commands to the Finder, we have to redirect them away from our script and at the
application object created by our application "Finder" specifier.
To do this, take the preceding tell statement and replace the target_object bit with
application "Finder". Here is how the resulting code should look:
tell application "Finder"
end tell
Now when AppleScript executes this piece of code, any commands that appear within
these two lines will be directed at the Finder application by default. With this
arrangement, you will be able to direct commands to any scriptable application on your
Mac—all you need to do is change the application name to the one you want. Powerful
stuff!
ABOUT APPLESCRIPT GRAMMAR: STATEMENTS
Let’s look at this new piece of code:
tell application "Finder"
end tell
In AppleScript, this structure is known as a statement—a compound statement to be exact. A compound
statement consists of an opening line and a closing line. The opening line starts with a keyword that tells
you what sort of statement it is—for example, the keyword if indicates a conditional statement while the
tell keyword indicates a tell statement.
The other kind of statement is a simple statement, which consists of a single line. The first two lines in our
script, with which we create our folder name, are both simple statements. For example, this is a simple
statement:
set date_string to date string of (current date)
The advantage of a compound statement is that it can contain any number of other statements. This allows
the compound statement to control how the statements within the block are executed when the script
runs. For example, a conditional statement can decide if the code it contains should be run or ignored,
whereas a tell statement specifies the default object that commands within the block should be sent to.
Okay, now that we have the Finder’s attention, let’s give it something to do.
Creating the Archive Folder
The first thing we want the Finder to do is to create a new folder. This folder should
appear within the user’s home folder, and it should use as its name the string object that
we created earlier and stored in the folder_name variable. Let’s start with the “making
the folder” bit, and then build up from there.
To create new objects in the Finder, we use the make command. The documentation for
this command appears in the Finder’s built-in dictionary, but we’ll have plenty of time to
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 3: AppleScript in Practice
43
explore application dictionaries in later chapters. For now, just follow along as I
construct the command a piece at a time.
First, type the make command’s name inside the tell block, like this:
tell application "Finder"
make
end tell
Now click the Compile button. As you can see, the script compiled successfully…always
a good first sign.
TIP: AppleScript cleans up any extra spaces and tabs when you compile the script, so don’t
bother tidying them yourself. AppleScript also automatically indents any lines that appear within
compound statements to make the overall structure of the code easier to see. For readability’s
sake, you may find it useful to insert blank lines between some statements—AppleScript leaves
those alone.
Licensed by
Jim Kilcullen
2884260
However, if you try to run the script now, you will get an error, because telling the Finder
just to “make” isn’t enough. You also need to tell it what to make—in this case, a folder
object. Here is the code to do this:
tell application "Finder"
make new folder
end tell
This indicates the class of object we want created: folder. When the script runs, this
object will be passed to the Finder as part of the make command. The make command
can take several values at once, however, so we need to label these values so that the
make command knows which is which. Having scripted the Finder before, I already know
that the label for this particular parameter is new, so that’s what I’ve used here. Just copy
what I’ve written for now, and in Chapter 5 I’ll show you how to look up this information
for yourself.
Now compile and run this script. If all goes well, Finder should create a new untitled
folder on the desktop. Congratulations! You’ve just created your first object in another
application. Figure 3–3 shows this script in action.
As you can see, the Finder has created a new folder on the desktop, which is the default
location it uses if you don’t specify a location yourself. You may notice something else
of interest here: when the make command finished executing, it returned a reference to
the newly created folder object. This is something we will make use of later.
So far we’ve prompted the Finder to create a new folder for us, but we’d really like to
refine this process a bit. The first task is to tell the Finder exactly where to make the
folder—specifically, in the user’s home folder.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
44
CHAPTER 3: AppleScript in Practice
Figure 3–3. The result of telling the Finder to make a new folder
Normally, when we want to identify an object somewhere in the Finder’s object model,
we have to create a reference to that location ourselves. On this occasion, however, the
Finder conveniently provides a built-in shortcut that will provide this reference for us.
This shortcut is named home, and it’s a property of the Finder’s application object.
(Don’t worry what that means for now; all will become clear in Chapter 5 when we
explore application scripting in depth.) To use this shortcut in the make command, just
add the label at followed by the word home:
tell application "Finder"
make new folder at home
end tell
If you run the script now, Finder will create a new untitled folder in your home folder.
The last bit of refinement is to tell Finder what the newly created folder should be called.
To do this, we need to retrieve our custom folder name string (which we stored earlier in
the folder_name variable for safekeeping), and then have the make command use this
value as the folder’s name when it creates it. This bit will take longer to explain, so for
now I will just show you the code for it:
tell application "Finder"
make new folder at home with properties {name:folder_name}
end tell
Run this script now, and you should see a new folder with a name like “Desktop Archive
for Friday, January 8, 2010” appear in your home folder.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 3: AppleScript in Practice
45
CAUTION: One limitation of the current script design is that if you run the script more than once
on the same day, the Finder will report an error like this: “The operation could not be completed
because there is already an item with that name.” Obviously this script isn’t quite as intelligent
as it could be—I’ll discuss how it might be improved in the final section of this chapter. For now,
I recommend that each time you test the script, you first check that it creates the archive folder
and moves all the existing desktop files into it. Once you’re satisfied that it has worked correctly,
move those files manually back to the desktop and drop the empty archive folder into the
Finder’s Trash before running the script again.
We will need to refer to this folder again when we move our desktop files into it, so to
finish this statement, insert an AppleScript set command to capture the folder reference
returned by the make command in a variable named archive_folder:
tell application "Finder"
set archive_folder to make new folder at home ¬
with properties {name:folder_name}
end tell
You might notice I’ve rearranged the make command a bit in the previous bit of code.
The whole line was getting a bit long, so I took advantage of another little AppleScript
feature, the line-continuation symbol (¬), to spread the code over two lines for neatness.
It is still a single simple statement, but the continuation symbol allows me to insert a line
break safely into the middle of it. When AppleScript sees the continuation symbol, it
simply continues reading on the next line as if the line break didn’t exist at all. To insert a
continuation symbol, just press Alt+L (users with non-US keyboard layouts may need to
use a different key combination).
TIP: AppleScript Editor also allows you to press Alt+Return to insert a continuation symbol
followed by a return.
Moving the Files
Our final task is to move all the files from the desktop into our new archive folder. For
this we use another Finder command, conveniently called move. The move command can
move a single object to another location, or, if we refer to several objects at once, it can
move them all together—a very elegant and powerful feature!
Here is how we refer to all the files on the desktop:
every file of desktop
This deceptively simple-looking reference is the key to the simplicity of our script. I
won’t explain exactly how it works here—that’s another job for Chapter 5—but rest
assured it does exactly what it claims to do: specify every single file on the Finder’s
desktop.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
46
CHAPTER 3: AppleScript in Practice
Let’s put the final command together. Insert a new line before the end tell line and type
the following:
move every file of desktop to archive_folder
When this line runs, the reference to every file of the desktop is created from scratch, while
the reference to our archive folder is retrieved again from the archive_folder variable.
Both references are then passed to the Finder as part of our move command. When the
Finder receives this command, it finds all the files identified by the first reference, and
moves them into the location identified by the second one. It’s that simple!
Final Thoughts
Congratulations on creating your first practical AppleScript! Obviously, I’ve kept this
particular exercise as simple as possible for the sake of readers who are completely new
to scripting, but hopefully it has given you some idea of the potential power available in
AppleScript.
Over time, you will pick up additional knowledge and skills that will enable you to design
and write much more powerful scripts entirely on your own. As you work through this
book, you might consider revisiting earlier projects such as this one and trying to
improve and enhance them yourself, either for practice or for your own personal use.
With that in mind, here are some ideas on how you might develop this project further…
Improving Reliability
When developing and testing a new script, you will often discover additional problems
that you hadn’t considered when you originally came up with the idea. In this case, you
may have noticed that while the Tidy Desktop script is pretty good at moving files into a
newly created archive folder, it does run into problems when an archive folder for the
same day already exists.
You will also find that often more than one way exists to solve a particular problem. For
example:
You could do nothing. If the script fails, it fails, and the user will just
have to accept that. In fact, there are plenty of situations where this is
the proper thing to do: for example, if a FileMaker Pro script requires a
particular database but the database file cannot be found, there’s no
point in the script trying to proceed any further. That said, it is often
useful to provide the user with a more helpful description of the
problem than just a raw application error. We’ll look at ways of dealing
with unexpected errors in Chapter 15. We’ll also look at ways of
presenting error messages and other basic information to users in
Chapter 16.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 3: AppleScript in Practice
You could ask the user for help. For example, if the script needs to
create a new folder but another folder with the same name already
exists, the script could display a dialog box asking the user to enter a
different folder name or to choose a different location in which to
create the new folder instead. Chapter 16 also explains how to present
file Open and Save dialog boxes to users.
You could take care of the problem yourself. In the case of the Tidy
Desktop script, the best solution might be to start by checking if an
archive folder for today already exists. If it does, just skip the “make
new folder” step and move the desktop items directly into the existing
folder. We’ll look at how to make these sorts of decisions in later
chapters, particularly in Chapter 14.
47
In fact, once you’ve gained a bit more knowledge and experience, I recommend you
revisit this and other early example scripts and see if you can improve them yourself. It’s
good practice, and will help to improve your design and testing skills. And perhaps you’ll
even find some of these scripts to be useful.
Adding Features
In addition to improving reliability, there are many ways in which you could modify or
extend the Tidy Desktop script in future to better fit your own needs. Here are a few
ideas:
You could make the script easier to use by saving it as a standalone
mini-application that the user can run just by double-clicking it in the
Finder. Or you could install it in the system-wide Script menu, allowing
the user to launch it from their own menu bar. We’ll look at these
options in Chapter 4.
You could create the archive folders in the user’s Documents folder, or
allow the user to set the location they want as a preference option.
You’ll learn how to construct your own references to application
objects in Chapter 5, and Chapter 11 includes a section on storing
values such as user settings between runs. And don’t forget Chapter
16 for help on displaying file and folder chooser dialog boxes.
You could extend the script to tidy away folders as well as files. Just
add an extra line, move every folder of desktop to archive_folder,
to the end of the tell application "Finder" ... end tell block. Or
you could restrict the script so that only document files or text
clippings are filed away. Chapter 5 looks at how to broaden or narrow
your references to identify different types of objects. (Just take care
not to refer to every item of desktop, however, as that would include
all visible disks as well!)
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
48
CHAPTER 3: AppleScript in Practice
You could modify the script so that different types of items are filed
away in separate locations. For example, you might move all text files
to your Documents folder, image files to your Images folder, video files
to Movies, and so on. Chapter 5 discusses how to construct
references that perform these kinds of filtering operations based on
individual attributes of your objects, such as file name extensions.
Once again, I encourage you to come back to this project later on and try your hand at
adding these and other enhancements yourself.
Documenting Your Code
Creating good documentation isn’t only for AppleScript engineers and scriptable
application developers. As a script writer, you will also find it useful to record useful bits
of information about the code you write. To help you in this task, AppleScript provides a
commenting feature that allows you to insert ordinary text within your script.
For small, quick scripts that you write once, run once, and then throw away, you likely
don’t need detailed documentation—you can probably keep any important information
you need in your head as you go, or make a quick note on the side. However, when
developing large, complex scripts or scripts that may be in use for many months or
years to come, good, detailed explanations can make a great deal of difference should
you or another scripter ever need to maintain or modify that script.
To add a single line of text that you want the script to ignore, precede it with a double
hyphen (--) or hash symbol (#). Any text starting after the double hyphen or hash
symbol, all the way to the end of the line, will compile as an inline comment; for
example:
display dialog "Hello World!" -- This is a comment
display dialog "Hello World!" # This is another comment
You can comment out whole blocks of text as well. You do that by starting the block
with (* and ending it with *). Here’s an example:
(*
Tidy Desktop
ABOUT
This script cleans up the user's desktop by moving all of its contents
into a dated 'Desktop Archive' folder.
HISTORY
- 2009-07-01 – v1.0; first release
KNOWN ISSUES
- If the desktop archive already exists, the make command will raise
an error.
TO DO
- Modify the script so that it only creates a new archive folder if
one doesn't already exist.
*)
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 3: AppleScript in Practice
49
This type of comment is great for longer explanations you want to add to your scripts.
Adding a sort of executive summary at the start of the script is a great way to explain
what the code does and how it does it.
Adding comments is essential if you or someone else needs to add functionality or fix a
bug in a piece of code that was written several months (or even years) ago. It is amazing
how difficult it can be to decipher even your own scripts after a while, after you no
longer remember what the different parts of the script are supposed to do.
For example, even in a simple script like Tidy Desktop, you might want to include a note
explaining why it doesn’t include the current time in the file name:
(*
Note: I originally tried using
but found that Finder gives an
file names. One solution would
(-) or period (.), but for now
*)
set date_string to date string
'current date as text' to include the time as well,
error as colons (e.g. "12:00:00 PM") are illegal in
be to find and replace all the colons with a hyphen
I'll just use the date only.
of (current date)
Summary
In this chapter, you worked through the process of creating your first “real-world”
AppleScript, putting into practice many of the concepts that were introduced in Chapter
2: AppleScript objects, commands, operators, and variables; and application objects
and commands.
These first three chapters provide only a taste of things to come, of course. In Part 2 of
the book, you will learn about all of these features in much more detail, along with other
features that you have yet to use, such as application dictionaries, conditionals and
repeat loops, and so on—knowledge you can use to build your own scripts entirely from
scratch.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
50
CHAPTER 3: AppleScript in Practice
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
51
Part
II
Understanding AppleScript
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
53
Chapter
4
Writing Scripts in
AppleScript Editor
Licensed by
Jim Kilcullen
2884260
Before we start exploring application scripting and AppleScript in detail, in this chapter
we are going to take a closer look at the main tool we will use in this book to create,
save, and run scripts: AppleScript Editor.
AppleScript Editor is a simple application for writing and running AppleScripts. You can
find it in your Mac’s /Applications/Utilities/ folder. The following sections describe
AppleScript Editor’s main features, starting with script windows, and then moving on to
other important features such as dictionary viewer windows, the Library window, and
preference options.
NOTE: On Mac OS X 10.5 and earlier, the AppleScript Editor application is named Script Editor
and can be found in /Applications/AppleScript/. There are a few other differences as
well, which I’ll point out as we go.
Working with Script Windows
AppleScript Editor’s script windows are where you edit and test your scripts. Figure 4–1
shows a typical script window. To create a new script window for yourself, just select
File ➤ New in AppleScript Editor’s menu bar.
As you can see, the script window is divided into two parts: the top pane is the area
where you can write your script, and the bottom pane is used by AppleScript Editor to
display various kinds of useful information.
The toolbar at the top of the window contains four buttons for performing basic
AppleScript actions: Record, Stop, Run, and Compile. A fifth button, Bundle Contents, is
only available when the script is saved in certain formats.
53
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
54
CHAPTER 4: Writing Scripts in AppleScript Editor
Figure 4–1. A script window in AppleScript Editor
At the bottom of the window are two buttons for changing the contents of the bottom
pane: Description and Event Log. When the Event Log option is selected, the three
buttons that appear immediately beneath the divider—Events, Replies, and Result (the
default)—allow you to control what is shown.
NOTE: In Mac OS X 10.5 and earlier, Script Editor has three buttons at the bottom of the script
window: Description, Result, and Event Log. These provide access to the same information, just
in a slightly different way.
Compiling a Script
Once you’ve typed some AppleScript code into the main window, the first thing to do is
to ask AppleScript to compile it. To do this, click the Compile button in the window’s
toolbar or select Script ➤ Compile in AppleScript Editor’s menu bar. AppleScript checks
your code to see if its syntax (grammar) is correct. If all is well, a tidied up version of
your source code appears in the top pane of the window. If a problem exists,
AppleScript Editor highlights the part of your code that’s causing the problem and
presents an error dialog box explaining why AppleScript couldn’t compile it.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 4: Writing Scripts in AppleScript Editor
55
TIP: When typing AppleScript code, it’s a good idea to click the Compile button regularly. This
allows you to check for any obvious typos as you work, and neatly indents any nested blocks of
code for you. You can also see how AppleScript has understood the various words in your script:
an AppleScript keyword, for example, is displayed as bold black text; an application-defined
keyword as blue or purple text; a user-defined variable or handler name as green text; and so on.
Running and Stopping a Script
The Run button, as its name suggests, is used to run the script that’s shown in the
window’s top pane. If the script isn’t already compiled, AppleScript Editor automatically
compiles it for you before running it.
If you need to force a running script to stop—for example, if you’ve just realized it’s
doing something wrong—just click the Stop button. You can also start and stop scripts
by using the Script menu in AppleScript Editor’s menu bar, or by pressing Cmd+R.
Recording a Script
Here’s recording in a nutshell: you click the Record button in AppleScript Editor, perform
some action in another application, and AppleScript Editor records that action in the
AppleScript language.
Okay, if recording a script is so easy, why do you need to write a script ever again?
Good question. Here’s the answer:
Although recording is nice, most applications aren’t recordable. The
recordability feature is rare, because application developers have to
put in a lot of extra work to add it.
When you record a script, you get computer-generated AppleScript
code consisting of a series of application commands, and nothing
else. If your script needs any conditional statements, repeat loops,
variables, or handlers, you will have to add these yourself.
Recording scripts is great if you can’t figure out how to script a specific aspect of an
application, and you’re lucky enough to be using an application that supports recording.
For instance, the Mac OS X Finder has some limited support for recording, which can
make your life a little easier when performing simple operations such as arranging Finder
windows on your desktop.
To test it, start a new script window in AppleScript Editor and click the Record button in
the toolbar. Then, create some new windows in the Finder, move them, rename some
files or folders, and move them around. When you are done, click the window’s Stop
button, and then look at its top pane of AppleScript Editor to see the recorded actions.
As you will see, some simple operations, including opening windows and creating and
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
56
CHAPTER 4: Writing Scripts in AppleScript Editor
renaming folders, are recorded in AppleScript Editor as AppleScript commands,
whereas others, such as moving and duplicating files, are ignored.
TIP: Another option for recording and replaying GUI interactions is Automator’s Watch Me Do
feature, first introduced in Mac OS X 10.5. Although recorded Automator actions cannot be edited
or modified to the same extent as recorded AppleScripts, Automator recording does not require
any special support from individual applications, so it can be used much more widely than
AppleScript recording.
Viewing the Result of Running a Script
Many scripts return a final result when you run them. You can view this value in the
bottom part of the script window—just select the Event Log tab and click the Result
button if they aren’t already selected. (Figure 4–1 at the start of the chapter showed a
typical script result.) This is the view you will use most often, whether to observe the
normal result of running a script or to check values returned while testing and debugging
parts of a larger script.
TIP: Starting in Mac OS X 10.6, if a script stops running due to an unexpected error, the Result
pane displays all the error information provided by AppleScript to help you debug your code. You
will learn all about errors and how to deal with them in Chapter 15.
Viewing the Events Sent by a Running Script
As I mentioned in Chapter 1, Mac OS X uses a special data structure, known as an
Apple event, to exchange commands between running applications. Whenever a script
directs a command at an application (or scripting addition), AppleScript converts the
command into an Apple event, allowing it to travel outside of the script and on to its
intended destination.
When the Events button of the Event Log tab is selected, AppleScript Editor allows you
to “spy” on all the Apple events that the script is sending, along with any replies it
receives (if the Replies button is also selected). This can be very useful when debugging
scripts that interact with other applications. Figure 4–2 shows a simple script and the log
it created while running.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 4: Writing Scripts in AppleScript Editor
57
Figure 4–2. Viewing the Event Log
NOTE: In Mac OS X 10.5 and earlier, Script Editor’s script windows use a slightly different
approach. There, you need to switch between the Event Log and Result panels by clicking the
buttons at the bottom of the window. Also, the Event Log panel records events only while it is
visible.
Adding a Description to a Script
Clicking the Description tab at the bottom of the script window in AppleScript Editor
reveals a large text field. You can write a description for your script and use the Format
menu to change the text’s type size, font, and color as you like, or copy and paste in
styled text from another application such as TextEdit. You can also have that formatted
text appear in a dialog box every time your script application launches. We’ll look at how
to do this in the “Customizing the Startup Screen” section later in the chapter.
Viewing Application Dictionaries
You can view the built-in documentation, or dictionary, of any scriptable application or
scripting addition using AppleScript Editor’s dictionary viewer. You can open a
dictionary viewer in several different ways:
Select File ➤ Open Dictionary in the menu bar and choose one or more
entries from the list of installed applications.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
58
CHAPTER 4: Writing Scripts in AppleScript Editor
Drag-and-drop an application or scripting addition file onto
AppleScript Editor’s application icon in the Finder.
Double-click an application or scripting addition name in AppleScript
Editor’s Library window.
Figure 4–3 shows a typical dictionary window showing part of TextEdit’s dictionary.
Figure 4–3. A dictionary viewer window displaying part of TextEdit’s dictionary
You will learn how to use the dictionary viewer in Chapter 5. For now, let’s move on to
examining AppleScript Editor’s other features.
Other Useful AppleScript Editor Features
Script and dictionary windows are the two main features of AppleScript Editor, but it has
plenty of other useful tools built into it as well, such as the Library window, the Result
and Event Log History windows, and customizable script formatting preferences. The
following sections look at these and other features.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 4: Writing Scripts in AppleScript Editor
59
Using the Library Window
AppleScript Editor’s Library window is an extremely handy feature if you write
AppleScripts on a regular basis. It provides a shortcut for opening the dictionaries of
your favorite applications and scripting additions. To open the Library window, just
select Window ➤ Library from AppleScript Editor’s menu bar.
Figure 4–4 shows a typical library.
Figure 4–4. The Library window
As you can see, the Library window comes with a selection of Apple-installed
applications and scripting additions already present. You can easily add new entries or
remove existing ones by clicking the “+” and “–” buttons in the window’s toolbar.
To open an application or scripting addition dictionary, just double-click the item you’re
interested in, or select one or more items from the list and click the “bookshelf” icon in
the window’s toolbar.
The Library window has one further trick up its sleeve: if you select an application name
and click the toolbar icon that looks like a script file, AppleScript Editor creates a new
script document containing a tell application ... end tell block that’s ready be to
filled in.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
60
CHAPTER 4: Writing Scripts in AppleScript Editor
Navigating to a Handler in a Script
In addition to the features discussed earlier, script editing windows have a couple of less
obvious features that will be of interest to more advanced users. One of these features is
the handler navigation menu that appears directly beneath the window’s toolbar, as
shown in Figure 4–5.
TIP: You can show and hide the navigation bar at any time by choosing View ➤ Show/Hide
Navigation Bar.
handler navigtion menu
Figure 4–5. The script navigation menu—in this example, the open handler has been chosen.
If you are working on a long script that contains a number of user-defined handlers, you
can use this menu to jump instantly to the point in the script where a particular handler
is defined. Just click the handler menu and pick the name of the handler you want.
TIP: The menu to the left of the handler navigation menu contains the name of the language
(AppleScript) that the script is written in. In theory, the language selection menu allows you to
select other OSA languages to write your scripts in, but because AppleScript is the only OSA
language included in Mac OS X, you normally can ignore this menu.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 4: Writing Scripts in AppleScript Editor
61
Viewing the Event Log History
The Event Log History window (Window ➤ Event Log History) keeps track of all script
results in chronological order. Figure 4–6 shows a typical Event Log History window.
Notice that the right pane has Events, Replies, and Result buttons, which work exactly
the same here as they do in a script window.
Figure 4–6. I ran the “random number” script multiple times, and the Event Log History feature captured them all.
In addition, the Event Log History window allows you to view historical “snapshots” of
any script that is run as long as the history window is already open. This can be
particularly useful when testing and debugging scripts. For example, if you run a script,
make some changes, and then run the script again, the Event Log History window will
remember what the script looked like each time it was run. To view the older version of
the code, just select the earlier entry in the history window and click the Show Script
button in its toolbar.
TIP: If you would like AppleScript Editor to record events even when the Event Log History
window is not open, uncheck the “Log only when visible” check box in the History panel of
AppleScript Editor’s Preferences window.
Scripting the AppleScript Editor
AppleScript Editor itself is scriptable. AppleScript can tell AppleScript Editor to make
new script documents, manipulate their source code, compile and execute them, and
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
62
CHAPTER 4: Writing Scripts in AppleScript Editor
save them to files. For example, run the following script; it will create a new script
document named “My Script” and then compile and execute it:
tell application "AppleScript Editor"
set script_doc to make new document with properties {name:"My Script"}
set text of script_doc to "say date string of (current date)"
compile script_doc
execute script_doc
end tell
Using Context Menu Scripts
Try Ctrl-clicking the script window to see the context menu that pops up. The bottom
half of the context menu contains a range of useful scripts, organized by kind, that will
do everything from inserting tell statements, repeat loops, and conditional statements
to adding error handlers. All of these scripts can be found in the
/Library/Scripts/Script Editor Scripts/ folder, which you can open by choosing
Open Scripts Folder from the context menu. Users who have administrator access can
add their own context menu scripts by placing them in this folder.
Viewing the Bundle Contents Drawer
The Bundle Contents drawer is another “hidden” feature of script windows. When you
are editing a compiled script or script-based application that has been saved as a
bundle, clicking the Bundle Contents icon in the window’s toolbar opens a drawer that
allows you to view and modify any resource files that are contained in the bundle.
NOTE: A bundle is a special “file” format that looks and behaves like an ordinary file in the
Finder but is really a folder in disguise. For instance, Mac OS X applications (.app files) are
almost always bundle based—the bundle contains all the resource files (icons, images, sounds,
etc.) that the application needs to do its job.
Figure 4–7 shows the extra resource files that are included in a typical bundle-based
script application created by AppleScript Editor.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 4: Writing Scripts in AppleScript Editor
63
Licensed by
Jim Kilcullen
2884260
Figure 4–7. Viewing the contents of a bundle-based applet
You will find the Bundle Contents drawer to be most useful when you are preparing
script applications that require extra support files to do their job. Although you could
distribute the applet and its supporting files grouped together in a single folder, if the
user doesn’t need to know about the support files, then a much better solution is to hide
all the support files inside the application bundle. As well as being tidier, this stops the
user from breaking your applet by fiddling with the support files or moving them to a
different location where they can’t be found.
To copy a file into the bundle, just drag it into the Bundle Contents drawer. You can edit
the bundle contents in other ways by clicking the drop-down menu at the top of the
drawer.
Later chapters will discuss how your applet’s main script can use commands from the
Standard Additions scripting addition to locate and read these files when it needs them.
Setting the Script Formatting Preferences
AppleScript Editor has a number of user-configurable preferences that you can
access via its application menu. One item of particular interest is the Preferences
window’s Formatting panel, shown in Figure 4–8, where you can change the fonts,
sizes, colors, and other formatting that AppleScript applies to your source code
when compiling a script.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
64
CHAPTER 4: Writing Scripts in AppleScript Editor
To change the formatting styles used, first select a category (Language keywords,
Comments, Variables and subroutine names, etc.) and then use AppleScript Editor’s
Font menu to alter its settings. (If you don’t yet know what all the different category
names mean, don’t worry: all these terms will be explained in the following chapters.)
Figure 4–8. The Formatting panel in AppleScript Editor’s Preferences window
TIP: An especially useful tip provided by AppleScript engineer Christopher Nebel is to change
the style for application keywords so that they are underlined. This will also underline any spaces
within keywords, making it easy to see where each keyword begins and ends; for example, path
to startup disk will appear as path to startup disk. To do this, go to the Formatting
panel and use Shift-click to select all the application-related keyword styles (Application
keywords, Command names, Parameter names, etc). Next, select Font ➤ Show Fonts to bring up
the Fonts palette. Click the pop-up menu in the top-left corner of the Fonts palette and select the
Single underline style.
Now that we’ve completed our tour of AppleScript Editor’s graphical interface, let’s
move on to examining the various file formats that we can save our scripts in, and the
features and benefits of each.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 4: Writing Scripts in AppleScript Editor
65
Saving Scripts
After you’ve written a script in AppleScript Editor, you’ll probably want to save it so that
you can use it again later, distribute it to other users, and so forth. There are four basic
file formats you can use: text, script, script bundle, and application. Table 4–1 provides
a brief summary of each.
Table 4–1. Basic AppleScript File Formats
Format
Description
Extension
Text
The script’s source code, saved as a plain text file
.applescript
Script
A compiled script file
.scpt
Script bundle
A bundle-based compiled script file
.scptd
Application
A simple stand-alone application, often called an
applet
.app
Icon
To save a script in AppleScript Editor, just select File ➤ Save As. Figure 4–9 shows a
typical Save dialog box. Notice the various menu and check box options near the
bottom of the dialog box—these will be discussed in the following sections.
NOTE: In Mac OS X 10.5 and earlier, Script Editor could save applets in two different formats:
single file (“Application”) and bundle based (“Bundle Application”). The old single-file format,
which only runs natively on PowerPC-based Macs, has been made obsolete by the newer
bundle-based format, which can run natively on 32- and 64–bit Intel Macs as well as PowerPC.
As of 10.6, AppleScript Editor always saves applets in the new bundle-based format.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
66
CHAPTER 4: Writing Scripts in AppleScript Editor
Figure 4–9. A typical Save dialog box in AppleScript Editor
Text-Based Scripts
The most basic format for saving script files is plain text. A plain text script file has the
file name extension .applescript and contains only the uncompiled source code for the
script. To save a script as plain text, select the Text option from the File Format menu in
AppleScript Editor’s Save dialog box.
The main advantage of the plain text file format is that it can be opened and viewed in
any plain text editor—TextEdit, BBEdit, TextWrangler, and so on. Another benefit is that
you do not need to have installed the applications and scripting additions used by the
script to be able to open and read the code. However, most of the applications that
actually run AppleScripts expect a complied script file, so you probably won’t use the
plain text format very often.
Compiled Scripts
A compiled script file is AppleScript’s default file format, and its file name ends in either
.scpt or .scptd. (The extra “d” indicates the script file uses Mac OS X’s special bundle
format, which we’ll discuss later.) To save a script as plain text, select the Script (or
Script bundle) option from the File Format menu in AppleScript Editor’s Save dialog box.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 4: Writing Scripts in AppleScript Editor
67
What is the difference between a compiled script and plain text? The big difference is
that AppleScript converts the original source code from AppleScript’s hallmark Englishlike syntax into a cryptic-looking binary format that can only be understood by the
AppleScript interpreter. A compiled script file containing the simple script display alert
"Hello!" looks like the following when viewed raw in Bare Bones Software’s BBEdit:
FasdUAS 1.101.10ˇˇˇˇ
lˇ˛ˇ˝
Iˇ¸ˇ˚ˇ¸.sysodisAaleRTEXT
m±Hello!ˇ˚ˇ˛ˇ˝ˇ˙
ˇ˙ˇ˘ˇ˘
.aevtoappnullÄê****
ˇ¯ˇ˜ˇˆˇıˇ¯.aevtoappnullÄê****
k
ˇÙˇÙˇ˜ˇˆˇÛˇÛ.sysodisAaleRTEXTˇı‡jascr
˙fifi≠
To convert, or decompile, a compiled script file back into human-readable AppleScript
code, just open it again in AppleScript Editor or another AppleScript editor such as
Smile or Script Debugger.
The compiled script file format has several advantages:
You can be certain that a compiled script file does not contain any
syntax errors because it has to be successfully compiled in order to
save it. (AppleScript code that cannot be successfully compiled can
still be saved in plain text format, however.)
Compiled scripts can contain data as well as code, allowing compiled
scripts to retain important values from one run to the next. Not all
applications support this feature, but when they do it can be very
useful. We’ll cover this ability in more detail when looking at script
properties in Chapter 11.
Compiled scripts can be loaded into other scripts. Chapter 19 will
discuss how more-advanced scripters can use this feature to share
frequently used pieces of code across many other scripts in a very
neat and efficient way.
Saving Scripts As Run Only
When saving a script in compiled format, you can choose the Run Only option to lock the
contents of your script so that it can no longer be read or edited by you or anyone else.
CAUTION: Before you save a script as Run Only, always save an editable copy of your script
under a different name first. Once a compiled script is saved as Read Only, it cannot be
decompiled. If you forget to keep an editable version of your script, or accidentally save over it
with your read-only version, you will have to rewrite the entire script from scratch if you ever
need to change it later on!
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
68
CHAPTER 4: Writing Scripts in AppleScript Editor
I personally never lock any of my scripts. As a consultant, I want my clients to open my
scripts and look at them. All they can say is, “Wow, we better not touch that stuff!” For
me, locking a script would be like Apple locking the containers of its computers so you
couldn’t open them.
Sometimes, however, saving scripts as Run Only is a good idea. The obvious reason is
to protect your scripting secrets, especially if your scripts are distributed to a mass
audience. Another reason is to prevent the users of the scripts from messing them up,
intentionally or unintentionally.
Saving Scripts As Bundles
Most of the time you will probably save your compiled scripts as ordinary .scpt files. If
you want to save a compiled script using Mac OS X’s special bundle format, select the
Script bundle option from the File Format menu in AppleScript Editor’s Save dialog box.
When you do this, two things happen. The first is that AppleScript Editor changes the file
name extension from .scpt to .scptd to indicate it is a bundle-based script. The second
is that the Bundle Contents button in the script window’s toolbar becomes active
(normally it is grayed out), allowing you to open the Bundle Contents drawer and
examine the contents of the bundle file.
Figure 4–10 shows the internal layout of the files and folders in a script bundle.
Figure 4–10. The structure of a basic script bundle, viewed in the Finder (top left) and AppleScript Editor (bottom
right)
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 4: Writing Scripts in AppleScript Editor
69
You can add additional files and folders to the script bundle by dragging them into the
Bundle Contents drawer, or by clicking the drop-down menu at the top of the drawer.
Later chapters will look at some of the useful things you can do with bundles.
Script-Based Applications (Applets)
Although the compiled script format is fine for scripts that will be used by other
applications, wouldn’t it be great if users could also run your scripts directly just by
double-clicking them in the Finder? Guess what—they can! Just select the Application
option from the File Format menu in AppleScript Editor’s Save dialog box, and
AppleScript Editor will save your script as a stand-alone mini-application, or applet, that
you can run just like any other Mac application.
In fact, why not try this right now? First, create a new document in AppleScript Editor
(File ➤ New) and type the following line of code:
display alert "Hello!"
Next, select File ➤ Save As to bring up the Save dialog box, select the Application
option in the File Format menu, name the file Hello.app, and click Save. Finally, find
your Hello applet in the Finder and double-click it. The applet will launch and display the
dialog box shown in Figure 4–11.
Figure 4–11. The dialog box displayed when the applet is run
Click the OK button to dismiss the dialog box and allow the script to proceed. Once the
script finishes running, the applet will quit automatically.
Applets are an ideal format to use when writing scripts for other people. They simply
download the applet, unzip it, and double-click the applet icon to run it—no extra
installation is needed!
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
70
CHAPTER 4: Writing Scripts in AppleScript Editor
Droplets
Droplets are script applets with a twist: they can process files that are dropped on them.
To turn an applet into a droplet, simply include an open handler somewhere in it. Don’t
worry if you don’t understand exactly what an open handler is yet; we’ll explore handlers
in much more detail in later chapters.
Figure 4–12 shows the code for a very simple droplet that tells you how many files and
folders were dropped on it.
Figure 4–12. The basic droplet script
Figure 4–13 shows the result of dropping three items onto the droplet in the Finder.
Figure 4–13. The result of dragging and dropping some files onto the droplet
Notice how the applet icon now includes a diagonal arrow to indicate that it’s a droplet.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 4: Writing Scripts in AppleScript Editor
71
Stay-Open Applets
If you want an applet to behave more like a regular desktop application and stay open
until the user quits it manually, just enable the Stay Open check box in the Save dialog
box. Stay-open applets have the advantage that they can respond to more than one
event. For example, if you resave the script in Figure 4–12 as a stay-open applet, once
it’s launched, you can drag files and folders onto it as often as you like. Figure 4–14
gives another example—perhaps you can guess what it does when saved as a stayopen applet and then launched in the Finder? (If not, don’t worry: you’ll learn all about
using the idle handler in Chapter 18.)
Figure 4–14. A simple example of a stay-open applet
Saving Applets As Run Only
Checking the Save dialog’s Run Only check box causes an AppleScript applet to be
saved in run-only form to prevent anyone from viewing or modifying its source code.
Remember to save an editable copy under a different file name first in case you need to
modify its code in the future!
Customizing the Startup Screen
When saving a script applet, you can check the Startup Screen check box, found in the
Save dialog box. The next time the applet runs, the text you typed in the Description
panel of your AppleScript Editor script window will display in a rather crude welcome
window.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
72
CHAPTER 4: Writing Scripts in AppleScript Editor
Figure 4–15 shows the script’s Description panel, which will be displayed when the
script applet is launched if the Startup Screen check box is checked when the applet
is saved.
Figure 4–15. You can add formatted text to the Description panel in the AppleScript Editor script window. This
text can be displayed when the script applet starts.
At this point we’ve covered all of the essential applications you will need to begin
developing and using your own scripts. Before we finish, however, let’s take a quick look
at several advanced tools that are worth exploring once you’ve gained a bit more
AppleScript experience.
Other Tools for Writing and Running AppleScripts
Although this chapter has focused on using Apple’s AppleScript Editor application to
create and run AppleScripts, plenty of other useful tools are available to AppleScript
developers and users. Before we move on to the next chapter, let’s take a moment to
look at some of the main options, several of which we’ll explore further in later chapters.
The System-wide Script Menu
The system-wide Script menu is an extremely useful Mac OS X extra that lets you run
compiled AppleScripts directly from your menu bar. The Script menu comes with
dozens of useful scripts already installed, and you can easily add your own scripts to it
as well.
The system-wide Script menu is disabled by default. To enable it, simply go to the
General panel of AppleScript Editor’s Preferences dialog box and check the “Show
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 4: Writing Scripts in AppleScript Editor
73
Script menu in menu bar” option. Once enabled, the Script menu sits neatly on the topright corner of the menu bar, alongside the usual Mac OS X “menulets” for controlling
volume levels, AirPort settings, and so on. Figure 4–16 shows the open Script menu.
NOTE: In Mac OS X 10.5 and earlier, you can use the AppleScript Utility application in
/Applications/AppleScript/ to enable the Script menu and set its preferences.
Licensed by
Jim Kilcullen
2884260
Figure 4–16. The open Script menu
To run a script from the Script menu, simply select it from the menu. To open a script
using the default AppleScript editor, select a script from the menu while holding down
the Option key.
The Script menu contains two additional items on top of the scripts and script folders. The
first item, Open Scripts Folder, opens the folders where the Script menu’s scripts are
stored, making it easy to add and remove your own. The second item, Open AppleScript
Editor.app, provides a handy shortcut for launching the AppleScript Editor application.
Where Are the Menu Scripts Stored?
As you can tell from looking at the menu shown in Figure 4–16 (or by gazing at your own
Script menu), it already has quite a few scripts. These scripts are provided by Apple and
come already installed in the /Library/Scripts/ folder of your startup disk.
The Script menu can contain up to three sets of scripts separated by divider lines.
The first set of scripts are those installed in /Library/Scripts/ and can be run by any
user. If you want to hide these scripts so that they don’t appear in the Script menu, just
uncheck the “Show Computer scripts” option in the General panel of AppleScript
Editor’s Preferences window.
The second set of scripts are those installed in your own personal ~/Library/Scripts/
folder and are only available to you. Because your own Scripts folder is empty by
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
74
CHAPTER 4: Writing Scripts in AppleScript Editor
default, you won’t see anything here initially. We’ll look at how to add your own scripts
to this location in just a moment.
The third set of scripts are those that you want to “belong” to one particular application.
For example, you may have written a script for tidying up your Finder desktop. If you
want this script to be visible in the Script menu only when the Finder is frontmost, just
put it in ~/Library/Scripts/Applications/Finder and the Script menu will hide or show
it depending on what application is active at the time.
Adding Your Own Scripts
Adding your own scripts to the Script menu is easy. Just select the Scripts folder that
you want from the Script menu’s Open Scripts Folder submenu, and the folder will open
in the Finder.
To open the system’s /Library/Scripts/ folder, choose the Open Scripts Folder ➤
Open Computer Scripts Folder option. Anyone can open and view these scripts in
AppleScript Editor, but you will need an administrator password if you want to add,
remove, or modify scripts in this folder.
Unless you want to share your menu scripts with other users on your Mac, the usual
place to put them is in ~/Library/Scripts/. To open this folder, choose Open Scripts
Folder ➤ Open User Scripts.
To add exclusive scripts for an application, activate that application (the Finder, for
example), and then from the Script menu, choose Open Scripts Folder ➤ Open Finder
Scripts Folder. Any scripts you place in that folder will appear only when the Finder is
active. If a folder for that application doesn’t exist, it will be created as you make your
selection.
TIP: While the system-wide Script menu is usually used to run AppleScripts, it can also run
scripts written in other scripting languages such as Perl, Python, Ruby, and bash. Just copy
these scripts into one of the Script menu’s Scripts folders and they’re ready to go!
Third-Party AppleScript Editors
In the world of third-party AppleScript editors, two names stand out in particular:
Satimage’s Smile and Late Night Software’s Script Debugger.
Smile
Satimage Software, the developers of Smile, describe it as “a programming and working
environment based on AppleScript.” To put it another way, Smile is both an AppleScript
editor and a highly customizable platform that more advanced users can build on to suit
their own particular needs.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 4: Writing Scripts in AppleScript Editor
75
Like AppleScript Editor, Smile can be used to write and run AppleScripts. A built-in
dictionary viewer provides easy access to application dictionaries, while an extensive
scripting interface allows many aspects of Smile to be controlled from AppleScript. On
top of this, Smile adds many interesting features of its own, including “terminal”
windows where you can type in or select any piece of AppleScript code and instantly
compile and run it; scriptable graphics windows that you can use to create graphs,
illustrations, and other images; and a simple toolkit for creating and adding your own
GUI dialog boxes to Smile.
Smile is available from the Satimage web site at http://www.satimage-software.com.
Several versions are provided: the standard Smile, which is free to download and use,
and two commercial options—SmileLab, which can be used for advanced data
processing tasks, and SmileServer, which can be used to build web applications in
AppleScript.
We will explore several of Smile’s more powerful and interesting features later on in
this book.
Script Debugger
Late Night Software proudly describe their Script Debugger as “The Ultimate
AppleScript Tool,” and I don’t think many AppleScripters would disagree with them.
Like AppleScript Editor, Script Debugger focuses on one task in particular: developing
AppleScripts. However, whereas AppleScript Editor provides only the basic tools
required to create and run scripts, Script Debugger is crammed full of powerful and
sophisticated features aimed at making intermediate and advanced AppleScripters’ lives
as easy as possible.
An advanced dictionary viewer ensures that every ounce of useful information is squeezed
out of application dictionaries and displayed to users, while an interactive object browser
allows users to explore the object models of running applications and examine their
contents in detail. Advanced testing features make it easy to run individual handlers within
a larger script to check that they work correctly, while clever packaging tools can examine
scripts and tell you what applications and scripting additions they rely on.
Script Debugger’s best-known feature, of course, is its powerful interactive AppleScript
debugger. The debugger allows you to pause and resume running scripts so that you
can examine their data at any time, and if anything goes wrong in your script, Script
Debugger can immediately provide extensive details on where the problem occurred
and what the script was doing at the time. We’ll take a look at debugging scripts with
Script Debugger in Chapter 29.
Script Debugger is available as a free demo or commercial purchase from the Late Night
Software web site at http://www.latenightsw.com.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
76
CHAPTER 4: Writing Scripts in AppleScript Editor
Developing GUI Applications
Although AppleScript’s main goal is to control other Mac OS X desktop applications, it
can be used to create them, too! A couple of options exist: Satimage’s Smile and the
new AppleScriptObjC framework introduced in Mac OS X 10.6. We’ll look at these later
in the book.
NOTE: In Mac OS X 10.5 and earlier, the standard Apple tool for developing GUI applications with
AppleScript was AppleScript Studio. However, although it is still possible to maintain existing
Studio-based projects in 10.6, AppleScriptObjC is now the standard platform for all new
development.
Command-Line Tools
Whereas AppleScript’s natural home is the Mac OS X desktop, many other scripting
languages happily live and work within Mac OS X’s Unix command-line environment.
Not to be outdone by the competition, AppleScript has responded with its own set of
command-line tools, including osacompile and osadecompile, which allow you to
compile and decompile AppleScripts from the command line, and osascript, which
allows AppleScripts to be run directly from the Mac OS X command line.
We will look at the various ways in which AppleScript and the Unix command line can
work together in Chapter 27.
Summary
In this chapter we looked at the basic tools for creating and running AppleScripts that
every AppleScript user should be familiar with: AppleScript Editor and the system-wide
Script menu. We also studied the various file formats that scripts can be saved in,
comparing the features and benefits of each.
One feature of AppleScript Editor that we haven’t really looked at yet is its powerful
dictionary viewer, used to examine the built-in documentation of scriptable applications
and scripting extensions. We will cover this in the next chapter, as you discover exactly
how application scripting works.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
77
Chapter
5
Understanding How
Application Scripting
Works
While the AppleScript language can be used for many general scripting tasks, by far the
most common and important use for it is automating desktop applications—which isn’t
surprising, as this is the main reason it was created in the first place. In fact, often when
people talk about “AppleScripting,” they don’t just mean scripting with the AppleScript
language, but application scripting as a whole! One point I make throughout the book is
that the AppleScript language is pretty small on its own. It has merely five commands
and a handful of objects. What makes AppleScript so powerful is the ease with which it
can interact with hundreds of scriptable applications and scripting additions, getting
them to do all the hard work so you don’t have to!
As you become an experienced scripter, you will learn the individual commands and
objects of specific applications that you need to script. First, though, you need to learn
the common features and behaviors that all scriptable applications share.
In Chapter 2, I introduced you to the four key concepts of scriptable applications:
How the application represents your data as objects
How the application lets you manipulate these objects using
commands
How the application organizes its objects into an object model
How the application documents its objects and commands in a
dictionary
In this chapter I will fill in all the details: how application objects are structured, how
commands are used, how the object model operates and how you navigate it, and how
to understand the information provided by the application dictionary.
77
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
78
CHAPTER 5: Understanding How Application Scripting Works
TIP: While reading through this chapter and the chapters that follow it, remember to refer back
to Chapter 2 any time you need to remind yourself how the pieces fit together. Also, don’t worry
if you don’t understand everything the first time you read it—after all, it is a very large quantity of
information to digest all at once!
A Quick Application Scripting Example
An application’s scriptability consists of two realms: objects and commands. Objects
represent the important pieces of information in your application, such as documents,
pages, and paragraphs. Commands are actions that you tell the application to perform:
save (a document), make (a new page), delete (a paragraph), and so on.
For instance, Apple’s TextEdit application includes a command named open that is used
to open text files. When TextEdit receives an open command, it reads each text file you
told it to open and creates a new document object containing the file’s contents.
Figure 5–1 shows how to open a file named TODO.txt that is located in the home folder
of the user named hanaan on the hard disk named Macintosh HD.
Figure 5–1. Sending an open command to the TextEdit application to open a text file
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
79
TIP: Notice the alias "..." expression in Figure 5–1. When the script runs, this creates an
AppleScript object that identifies a particular file, folder, or disk—in this case, the TODO.txt file.
AppleScript’s alias objects will be fully explained in Chapter 17. For now, all you need to know is
that TextEdit’s open command requires one or more alias objects that identify the text file(s) you
want it to open.
When the script runs, as you’d expect, a new window containing the file’s text appears
in TextEdit’s graphical user interface (GUI).
However, that’s not all that happens. Beneath the surface, TextEdit creates a new
document object that contains the text from the file and is responsible for managing any
changes that you may make to it. And since TextEdit is scriptable, you can see this
object directly from AppleScript, and manipulate it too.
In fact, the last thing that the open command does, once it has read the file into a new
document object, is to return a reference to the new document object, as shown in the
Result pane in Figure 5–1.
As you will see later in the chapter, references are a vital part of working with objects in
a scriptable application, with each reference acting as a series of directions that allows
you to locate a specific object (or objects) within the application’s object model. In this
case, the reference document "TODO.txt" of application "TextEdit" identifies a
document object named “TODO.txt” within the application named “TextEdit”.
NOTE: If you want to try the script in Figure 5–1 yourself, just create a text file named
TODO.txt in your home folder and replace the hard disk and user folder names in the script to
match your own. A number of the scripts in this book that work with files use hard-coded paths
like this for simplicity, but as every user’s file system is different, you may need to tweak these
paths for the scripts to work correctly on your Mac.
Understanding Objects
Objects have three important characteristics: class, properties, and elements. Let’s
consider each of these in turn.
How Objects Are Categorized by Class
Humans love to categorize things; it’s part of our nature. With applications representing
lots of different kinds of data—disks, folders, and files in Finder; tracks and playlists in
iTunes; and so forth—it’s not surprising that the different kinds of objects that appear in
scriptable applications should be categorized too.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
80
CHAPTER 5: Understanding How Application Scripting Works
We describe all objects of a particular type as belonging to the same class. For example,
in the Finder, all of the objects describing mounted disks belong to the disk class; in
TextEdit, all of the objects representing your open documents are members of the
document class.
Knowing the class of an object is essential for figuring out what you can and can’t do
with it. For example, if you are dealing with an object of class disk, you can be pretty
certain that it has a name (for example, “Macintosh HD”) and a format (HFS+, NTFS,
UFS, etc.), can contain any number of files and folders, and can be ejected from the
system (assuming it isn’t the startup disk). If you are dealing with an object of class
folder, you can safely assume that it also has a name and can contain files and folders,
but doesn’t have a format and can’t be ejected. If you are dealing with an object whose
class is document file, then you can assume that it too has a name, that it doesn’t
contain any files or folders, and that you can tell the Finder to open it in the application
that created it.
NOTE: The Finder may have thousands of document file objects—each one unique—yet all of
these document file objects have exactly the same structure. This structure is defined by the
Finder’s document file class and can be viewed in AppleScript Editor’s application dictionary
viewer. You will learn how to do this in the “Understanding Application Dictionaries” section later
in the chapter.
To identify the exact class that a particular object falls into, scriptable applications
normally provide each object with a property named, not surprisingly, class. The value
of the class property is the name of the class that the object belongs to.
For instance, in Figure 5–1, you saw that TextEdit’s open command returned a reference
to an application object. Script 5–1 sends a second command, get, asking TextEdit for
the class of the object being referred to. As you might guess, the class of the object in
this case is document.
Script 5–1.
tell application "TextEdit"
open alias "Macintosh HD:Users:hanaan:TODO.txt"
get class of result
end tell
--> document
Notice how the class name appears as a keyword. Don’t confuse class names with
AppleScript strings, which appear as text surrounded by double quotes. Class names
are application-defined symbols; strings are user-defined text.
Incidentally, AppleScript values also have a class property:
class of "Hello, World!"
--> text
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
81
Even class name objects have a class property:
class of document
--> class
There is a bit more to the class-based categorization scheme than I’ve described so far,
but we’ll get to that later.
Introducing Object Properties
Properties are the object’s traits. If your car was an object in the application of your life,
its properties would include the car’s color, manufacturing year, make, model, plate
number, and so on. Each property appears only once in an object. Your car can’t have
more than one plate number, for example.
A Finder object of class document file may have properties such as the size, creation
date, and icon position of the file, while an InDesign object of class image may include
properties describing the image’s rotation angle, resolutions, and bounds.
Here are some of the properties you can find in an iTunes object of the class user
playlist:
name (text) : The name of the playlist
duration (integer, r/o) : The total length of all songs (in seconds)
special kind (none/Audiobooks/folder/Movies/Music/Party Shuffle/
Podcasts/Purchased Music/TV Shows/Videos, r/o) : Special playlist ¬
kind
parent (playlist, r/o) : Folder which contains this playlist (if any)
Each description consists of the property name in bold, followed by the class of object it
contains in parentheses, and finally a brief description of its purpose.
For example, the name property contains an AppleScript string (an object of class text),
which is the name of that playlist—“Library”, “Music”, “Movies”, “Top 25 Most Played”,
or whatever.
Notice that most of the properties shown here are marked r/o, which is short for “readonly.” You can get the current value of a read-only property using AppleScript, but you
cannot modify it. Only the name property allows you to get and set its value however you like.
In most cases, the properties of an application-defined object describe the ordinary,
day-to-day details of that application object. Most of these properties contain plain old
AppleScript values such as numbers and text. For example:
tell application "iTunes" to get name of playlist 1
--> "Library"
tell application "iTunes" to get duration of playlist 1
--> 43145
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
82
CHAPTER 5: Understanding How Application Scripting Works
A few of these properties contain symbol-style values, known as constants, which are
defined by the application itself.
NOTE: You may also occasionally see constant objects referred to as “enumerations,”
“enumerated types,” or “symbols,” which are terms commonly used in other programming
languages.
Constants are typically used when the value of a property needs to be one of a number
of predefined options; think of it as a “multiple-choice” setting. For example, the special
kind property of an iTunes playlist must contain one of the following constant objects
only: none, Audiobooks, folder, Movies, Music, Party Shuffle, Podcasts, Purchased
Music, TV Shows, or Videos. For instance:
tell application "iTunes" to get special kind of playlist "Library"
--> none
tell application "iTunes" to get special kind of playlist "Movies"
--> Movies
Notice how each constant is made up of a word (or phrase). You can tell that it is a
constant rather than a text object because text objects are displayed as a pair of double
quote marks with the text in between. Instead, each constant is defined as a keyword in
the application dictionary, allowing you to write it directly in your script.
TIP: Another way you can tell that the result is a constant is that AppleScript Editor will show
application-defined constant keywords as plain purple text, whereas AppleScript objects appear
in black. (This is assuming you are running Mac OS X 10.6 and haven’t changed the default
settings in AppleScript Editor’s Formatting preferences, of course.)
In special cases, an object property will contain not an AppleScript object but another
application object, or—to be exact—a reference to another application object. For
example, if a playlist object is stored inside a playlist folder, as shown in Figure 5–2, then
its parent property will contain a reference to the playlist folder that contains it.
Figure 5–2. A playlist folder containing several playlists, as seen in iTunes’ GUI
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
83
If you are dealing with one of these nested playlist objects and need to know what
playlist folder it is in, you can find out just by asking the playlist object, like this:
tell application "iTunes" to get parent of playlist "80's Music"
--> folder playlist id 147 of source id 43 of application "iTunes"
The resulting reference object is a bit cryptic to look at, but it is pointing to the object
that represents the playlist folder named “Music by Decade” in the preceding example.
To check this, ask the folder playlist object for its name:
tell application "iTunes" to get name of parent of playlist "80's Music"
--> "Music by Decade"
Another good example is the home property of the Finder’s main application object. This
contains a reference to the current user’s home folder. This isn’t the only way to locate
the user’s home folder, but it provides a very convenient shortcut for identifying it
quickly and reliably:
Licensed by
Jim Kilcullen
2884260
tell application "Finder" to get home
--> folder "hanaan" of folder "Users" of startup disk of application "Finder"
A particularly interesting feature provided by most scriptable applications is the
properties property. When you get the properties property of an application object, the
result is an AppleScript object, called a record, that contains the current values of many
or all of the object’s properties:
tell application "Finder" to get properties of home
--> {class:folder,
name:"hanaan",
index:3,
displayed name:"hanaan",
name extension:"",
extension hidden:false,
container:folder "Users" of startup disk of application "Finder",
disk:startup disk of application "Finder",
position:{-1, -1},
desktop position:missing value,
bounds:{-33, -33, 31, 31},
kind:"Folder",
label index:0,
locked:false,
description:missing value,
comment:"",
size:missing value,
physical size:missing value,
creation date:date "Sunday, October 4, 2009 10:11:37 AM",
modification date:date "Wednesday, March 3, 2010 10:53:05 PM",
icon:missing value,
URL:"file://localhost/Users/hanaan/",
owner:"hanaan", group:"staff",
owner privileges:read write,
group privileges:read only,
everyones privileges:read only,
container window:container window of folder "hanaan"
of folder "Users" of startup disk of application "Finder"}
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
84
CHAPTER 5: Understanding How Application Scripting Works
This can be a great way to find out lots of information about an object, particularly when
exploring an application’s object model in AppleScript Editor to see what it contains.
Introducing Object Elements
The elements of an application object play a very different role from its properties.
Whereas properties provide basic information about the object itself, and occasionally
provide a useful shortcut to another object of interest, the only purpose of an application
object’s elements is to tell you about the other application-defined objects it contains. In
particular, while an object can only have one of each property, it can have any number
of elements you like, including none at all. You can also perform a much wider range of
actions on elements, compared to properties. In addition to getting an object’s existing
elements, you can add new ones, delete them, move or duplicate them, and so on.
All application objects contain properties, although not all have elements. For example,
in the Finder, a folder can contain other folders, application files, document files, and so
forth. These nested files and folders are represented as elements of the folder object
that contains them. By comparison, files in the file system don’t contain other items, so
while file objects have properties, they don’t have any elements.
Here are the different types of objects that a Finder folder object can contain:
Folders
Alias files
Application files
Document files
Internet location files
Clippings
Packages
Most of these should sound familiar, since you deal with these file system objects all the
time in the Finder’s GUI. Folder objects represent folders in the file system, document
files (.txt, .jpg, .doc, etc.) contain information, clippings are desktop clipping files
(.textClipping, .pictClipping), and so on. The only one that might not be obvious is
“package,” a special format that appears as a file but is really a folder in disguise, but
you’ll find out more about packages later on in the book.
For example, the script shown in Figure 5–3 asks the Finder for all of the folder
elements of the current user’s home folder.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
85
Figure 5–3. Asking the Finder for all the folder elements of a folder object returns a list of references, one to
each element.
When you run the script, the result is a whole list of references, each one identifying a
particular folder element contained by the folder object that represents the user’s
home folder.
You can refer to the elements of an object in various ways, including by position (index),
by name (if they have one), all at once, or even by testing them to see if they match your
exact requirements by using the powerful whose clause. We’ll study these and other
reference forms later on in the “More on Constructing References” section.
In Figure 5–3, I used a reference to all of the folder elements of the home folder, while
each of the references returned identified each folder element according to its name.
In the following iCal example, I refer to the first event element of the calendar element
named “Home”:
tell application "iCal"
event 1 of calendar "Home"
end tell
If I run this script, the result is a fresh reference to the object that was found:
--> event id "E0BE7912-6D89-4831-9B48-05621C1D9F2A"
of calendar id "EE4AE213-DB53-460A-82A9-0BB856FC3890"
of application "iCal"
This reference identifies elements in yet another way, by using unique identifiers.
Although it may not be so pretty to look at, because iCal gives each of its objects a
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
86
CHAPTER 5: Understanding How Application Scripting Works
unique ID that never changes, this kind of reference is highly reliable if you need to find
that particular object again later on in a script.
Understanding elements is key to understanding how objects are organized into an
object model. There is a lot more still to learn, but let’s not get ahead of ourselves. We’ll
come back to elements soon enough in the “Understanding the Application Object
Model” section, but for now let’s spend a bit of time discussing the second key concept
in application scripting: commands.
Understanding Commands
Compared to objects, commands are a breeze to understand. Yet commands are every
bit as crucial to application scripting as objects. Commands make things happen, and
without them, all of those valuable objects would be utterly useless.
Most of the commands you use in AppleScript are defined by scriptable applications.
One application command may create a new document in TextEdit; another may play a
song in Apple iTunes. Other commands could create new files and folders, send e-mails,
or resize images…the list of possibilities is almost endless!
NOTE: Scriptable applications are not the only sources of commands for scripts to use.
Commands can also be defined by scripting additions, special plug-ins that add useful
commands for working with AppleScript’s own built-in objects. For example, the Standard
Additions scripting addition provides commands for displaying dialog boxes, reading and writing
files, and so on. In addition, AppleScript provides five built-in commands (get, set, copy,
count, and run), and you can define your own commands by adding script handlers to your
AppleScripts.
So, what makes up a command?
For starters, every command must have a name. For example, earlier in the chapter you
encountered the command called open that is provided by TextEdit for opening text files.
In addition, many commands can also have parameters. These are objects, provided by
your code, that will be passed to the application to use when processing the command.
In order for the command to have an effect, it must be sent to an object. This object is
known as the command’s target. When working with scriptable applications, the target
is an object that represents the application.
Many commands return objects as their result. If a command fails for some reason, an
error will be generated instead.
The following sections will explore each of these concepts in turn.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
87
Introducing Command Names
Every command has a name. When an application object receives a command, it
checks whether it contains a handler with the same name. If it does, it responds to the
command by executing the code in the handler.
Here are some common application-defined command names: make, move, duplicate,
delete, and close. You will see these names frequently, as most scriptable applications
provide these commands for manipulating objects in their object models. Some
applications also provide commands for performing more specialized tasks, such as
play, check syntax, and shut down (found in iTunes, AppleScript Editor, and System
Events, respectively). There are even a few commands that all applications will
understand, whether they are scriptable or not: run, activate, open, and quit.
Here are some examples of simple commands:
tell application "TextEdit"
activate
end tell
tell application "iTunes"
play
end tell
tell application "System Events"
shut down
end tell
Introducing Command Parameters
Most command handlers require extra information to do their jobs. The command itself
must supply the values to use—we call these values parameters. For example, the
following open command requires a single parameter, an AppleScript alias object
identifying the file you want to open in TextEdit:
tell application "TextEdit"
open alias "Macintosh HD:Users:hanaan:Notes.txt"
end tell
Some commands, such as open, take a direct parameter, where the value appears
immediately after the command name.
Many commands also take labeled parameters, where each value is identified by a
keyword. For example, the following make command requires a labeled parameter that
tells it the class of object to create:
tell application "TextEdit"
make new document
end tell
The parameter’s label is new and its value is an object representing the class name:
document.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
88
CHAPTER 5: Understanding How Application Scripting Works
At most, a command can have one direct parameter, but it can have any number of
labeled ones. For example, the Finder’s duplicate command, which is used to duplicate
files and folders, has the following definition:
duplicate v : Duplicate one or more object(s)
duplicate specifier : the object(s) to duplicate
[to location specifier] : the new location for the object(s)
[replacing boolean] : Specifies whether or not to replace items in the
destination that have the same name as items being duplicated
[routing suppressed boolean] : Specifies whether or not to autoroute items
(default is false). Only applies when copying to the system folder.
--> specifier : to the duplicated object(s)
This command takes a direct parameter along with three labeled parameters, named to,
replacing, and routing suppressed:
The direct parameter is a reference to the Finder object, or objects, to
be copied; in this case, one or more files and/or folders.
The to parameter is a reference to the object (in this case, a folder or
disk), where the items are to be copied to.
The replacing parameter is a value that tells the handler for the
duplicate command whether it should overwrite any existing items
that have the same names as the items being copied.
The parameter named routing suppressed is a holdover from the days
of Mac OS 9, when copying control panel, font, and extension files to
the system folder would automatically put them in the appropriate
subfolders.
The following script demonstrates how to copy every document file on the current user’s
desktop into their Documents folder:
tell application "Finder"
duplicate every document file of desktop ¬
to folder "Documents" of home ¬
replacing false
end tell
As you can see, we are using the Finder’s duplicate command, giving it three
parameters to work with:
The direct parameter is a Finder reference to all of the document files
on the user’s desktop: every document file of desktop.
The to parameter is a reference to the user’s Documents folder: folder
"Documents" of home.
The replacing parameter is an AppleScript object, false.
You’ll notice I haven’t included a routing suppressed parameter. While some application
commands require all parameters to be supplied by your script, other commands may
allow some or all parameters to be omitted. When you do not supply an optional
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
89
parameter, the application will use a sensible default value instead. In this case, if you
omit the routing suppressed parameter, the Finder will use the default value of false.
If you want, you can also omit the to and/or replacing parameters. Omitting the to
parameter causes the Finder to make copies in the same folder, just as if you select the
files in the GUI and choose File ➤ Duplicate. If you omit the replacing parameter, the
duplicate command will use the default value, which is false. This will cause the
duplicate command to generate an error if you try to replace any existing files in the
Documents folder. (If the replacing parameter is true, any existing files will be replaced
without warning, so be careful.)
There is one more thing you will notice about this command. When you compile it,
AppleScript magically transforms the replacing false part into without replacing to
make it easier to read. We’ll discuss this further in Chapter 12.
Commands Must Be Targeted at Objects
To have an effect, a command must be sent to an object that knows how to handle it.
When scripting other applications, this is an object of class application that
represents the program you want to script. Here is the basic syntax for creating an
application object:
application application_name_or_path
To make targeting commands easy, AppleScript provides the tell block statement,
which you already met in Chapter 3. You can use a tell block to specify the default
target for all the commands inside the block, which can be especially convenient when
you want to direct several commands to the same location.
Here is the syntax for AppleScript’s tell statement:
tell target_object
-- One or more statements here...
end tell
If the tell block contains only a single statement, then you can, if you wish, shorten it to
this:
tell target_object to some_statement
In Script 5–2, the target for the sleep command is the System Events application.
Script 5–2.
tell application "System Events"
sleep
end tell
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
90
CHAPTER 5: Understanding How Application Scripting Works
Here’s how the script works:
1.
When the application "System Events" expression is executed, it
creates an object of class application identifying System Events.
2.
The tell block makes this object the default target for all of the
commands inside the block.
3.
When the sleep command inside the tell block is run, it is sent to the
object identified by the tell block, application "System Events".
4.
The application object transforms this command into an Apple event, a
special data structure that Mac OS X uses to pass commands between
GUI applications, and sends it to System Events.
5.
System Events recognizes this command as one of its own, and
performs the appropriate action—putting your Mac to sleep, in this
case. The part of the application that responds to the command is
called a handler.
NOTE: If the target application is not already running, AppleScript will automatically launch it
before sending it the command. This is normally the behavior you want. However, if you wish to
find out if an application is running before sending it commands, you can check the
application object’s running property first. We’ll discuss this and other features of
application objects in the “More on application Objects” section later in the chapter.
Commands Can Return Results or Report Errors
Many commands return an object as a result. With some commands, usually those that
process data, returning a value is their only purpose. For instance, you can use the
Finder’s exists command to check for the presence of a particular file, folder, or disk.
The result is an AppleScript object (either true or false) that tells you whether or not the
desired item could be found:
tell application "Finder"
exists folder "Applications" of startup disk
end tell
--> true
Other commands may perform an action and then return a useful value related to the
outcome of that action. For example, the purpose of the Finder’s make command is to
create a new file or folder on one of your disks, which it does. In addition, it returns a
reference to the object it just created:
tell application "Finder"
make new folder at home
end tell
--> folder "untitled folder" of folder "hanaan"
of folder "Users" of startup disk of application "Finder"
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
91
This can be useful if you need to refer to that object later in the script: just assign the
returned reference to a variable, and the next time you need it you can get it from the
same variable. In the following script, the second line stores the reference to a newly
created folder in a variable named the_folder. The third line then retrieves the reference
from that variable and uses it as the parameter to the Finder’s open command to open
the folder onscreen:
tell application "Finder"
set the_folder to make new folder at home
open the_folder
end tell
Commands that run into unexpected problems while performing a task usually generate
an error to let the script know that something has gone wrong. For example, unless you
happen to have a thousand folders in your home folder, the open command in the
following script will raise an error when you try to run it:
tell application "Finder"
open folder 1000 of home
end tell
The message describing this error is “Finder got an error: Can’t get folder 1000 of
home.” In addition to a human-readable description, other information such as error
number codes and the value that caused the problem may be provided, allowing scripts
to work out what the problem is and try to sort it out themselves, if they want.
NOTE: Chapter 15 will explain errors and error handling in detail.
At this point, we have still not covered the finer details of working with application
commands, but don’t worry; what you have learned here is more than enough to get
you started. We will come back to the subject in Chapter 12 when we discuss
commands in general.
Now that you’ve filled out your knowledge about how individual objects and commands
work, it’s time to proceed to the third key concept in application scripting: how
scriptable applications organize their objects into an object model.
Understanding the Application Object Model
Perhaps the most compelling part of scripting an application is working with its object
model. The object model is used to organize large amounts of program data so that you
can navigate it effectively to find the information that you want. Most scriptable
applications have an object model—only those with particularly simple or limited
scripting support can do without one.
Earlier in the chapter you learned how individual application objects are structured. Each
object in a scriptable application usually has one or more properties containing simple
AppleScript values such as numbers and text that tell you something about that object.
In addition, some application objects can also contain other application objects, either
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
92
CHAPTER 5: Understanding How Application Scripting Works
stored in properties or represented as elements. In turn, some of those objects may
contain other objects, and so on, until the position of every last scriptable object in the
application has been identified.
This type of structure is called an object model, and the way it fits together is described
as a containment hierarchy.
Let’s now look at exactly how the object model of a scriptable application is put
together.
How Objects Can Contain Other Objects
Although different applications have different types of objects (the Finder has files and
folders, Adobe InDesign has pages and text frames, and so on), most applications’
object models follow the same overall structure: a single, top-level object of class
application that contains a number of objects, some of which contain other objects,
and so on.
To understand this structure, imagine a large office building. (This building is equivalent
to a scriptable application.) The building is divided into floors, each floor is divided into
offices, and an office may have desks and people in it. Every office has a specific
address that anyone in the building can use to find it.
Figure 5–4 shows a cutaway view of the building to help you visualize its internal
structure.
Once you know how the building is laid out, you can easily find your way around it. For
instance, the receptionist’s desk is the third office on the second floor. The office also
has a name, “Reception”, so another way you could identify it would be by saying “the
office named ‘Reception’ on the second floor.” Notice that you can identify the desired
office by two different approaches: by its position and by its name.
In AppleScript, locating objects in order to script them is the first order of the day.
Scriptable applications use a similar method of organizing their objects as our fictional
office building. For example:
The Finder application has disk objects that can contain file and folder
objects. Folders can have files or more folders.
In InDesign, you have document objects, each of which contains page
objects. The pages may contain, among other things, text frames that
can contain words and characters.
In FileMaker Pro, you have database objects that can have tables with
fields and records.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
93
Licensed by
Jim Kilcullen
2884260
Figure 5–4. The office building described as an object model
How AppleScript Refers to Application Objects
Just as you can follow a set of directions to arrive at a specific office in a building, so
can AppleScript provide a set of directions to locate a particular object (or, in some
cases, several objects at once) in an application’s object model. We call this set of
directions a reference.
NOTE: When talking about application references, the AppleScript Language Guide for Mac OS X
10.5+ uses the term object specifier, while AppleScript Editor uses just specifier. However, every
AppleScript user I know says reference—the traditional term since AppleScript was invented—
so we will continue to call them references throughout this book.
Identifying objects in scriptable applications is also similar to the building example. For
instance:
In the Finder, you can refer to the document file named “report.txt” in
the third folder of the disk named “Server”.
In InDesign, you can refer to the fifth text frame of page 2 in the
document named “Annual Report.indd”.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
94
CHAPTER 5: Understanding How Application Scripting Works
In FileMaker Pro, you can refer to the cell named “Last Name” in
record 5 of the table named “Contact” of the front database.
Each application has completely different types of objects, but the way each object
model works is pretty much the same.
Here is how we can write these directions in AppleScript itself:
tell application "Finder"
document file "report.txt" of folder 3 of disk "Server"
end tell
tell application "Adobe InDesign CS3"
text frame 5 of page 2 of document "Annual Report.indd"
end tell
tell application "FileMaker Pro"
cell "Last Name" of record 5 of table "Contact" of database 1
end tell
HOW ENGLISH-LIKE CAN APPLESCRIPT CODE BE?
One of AppleScript’s most striking features is that, if you wish, you can make your scripts look remarkably
close to written English. For example, the document file named "report.txt" in the third
folder of the disk named "Server" is not just natural English—it also makes a perfectly good
AppleScript reference when written inside a tell application "Finder" ... end tell block.
For starters, notice how the appears several times in the reference. You can insert the keywords almost
anywhere in your code—they don’t do anything except make your code look more English-like. The reference
also uses third folder instead of folder 3 and disk named "Server" rather than disk "Server".
You do have to be careful, though. Just because AppleScript allows you to make your code look like
English, it doesn’t mean that AppleScript can actually understand English. Although AppleScript’s grammar
and vocabulary may be more flexible than that of most programming languages, they still follow their own
particular set of rules—and these rules are strictly enforced. For example, when talking to InDesign,
AppleScript allows you to say the fifth text frame of page 2 but not the fifth text frame
on page 2, even though either phrase would be acceptable in English. The AppleScript compiler will
recognize either of or in when used as prepositions in a reference, but not on, which has a totally
different purpose as far as AppleScript is concerned.
In practice, although AppleScript does allow for some clever phrasing, most scripters ultimately prefer to
keep their code simple and consistent and avoid the fancy but nonessential stuff. For example, document
file "report.txt" of folder 3 of disk "Server" may not look as attractive as the more
“natural” phrasing shown previously, but it is clear and to the point. (Plus, it takes less work to type!) As
you use AppleScript more, you will come to find the coding style that best suits you.
You can assemble references in several different ways. For instance, the reference
tell application "Finder"
application file "TextEdit.app" of folder "Applications" of startup disk
end tell
can also be written using AppleScript’s possessive 's form, like this:
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
95
tell application "Finder"
startup disk's folder "Applications"'s application file "TextEdit.app"
end tell
Both approaches work in exactly the same way, so just use whichever one you find
most readable.
A third option is to build up the reference one bit at a time using nested tell blocks:
tell application "Finder"
tell startup disk
tell folder "Applications"
application file "TextEdit.app"
end tell
end tell
end tell
This produces exactly the same reference as before—you can check this by running all
three scripts in AppleScript Editor and comparing the results. In each case, Finder will
return a new reference that looks like this:
--> application file "TextEdit.app" of folder "Applications"
of startup disk of application "Finder"
Nested tell blocks make it easy to use the same reference across several commands
without having to type it out each time. Script 5–3 gathers some information on the
currently playing track in iTunes and displays it to the user.
Script 5–3.
tell application "iTunes"
play
set the_track_name to name of current track
set the_album to album of current track
set the_artist to artist of current track
end tell
display dialog "Now listening to " & the_track_name ¬
& " of " & the_album & " by " & the_artist & "."
The code works, but is somewhat repetitive when identifying the current track property.
With a longer reference, this would become even more awkward to read and maintain.
Script 5–4 eliminates the repetition by using a tell block to identify the application
object’s current track property as the starting point for assembling references within
the block.
Script 5–4.
tell application "iTunes"
play
tell current track
set the_track_name to name
set the_album to album
set the_artist to artist
end tell
end tell
display dialog "Now listening to " & the_track_name ¬
& " of " & the_album & " by " & the_artist & "."
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
96
CHAPTER 5: Understanding How Application Scripting Works
How do these tell blocks work? Well, there are two ways you can compose a literal
reference in your code: as an absolute reference, or as a relative reference. An absolute
reference describes the object where the entire search begins. In application scripting,
this is always an application object. For example, the following literal references are all
absolute because they start by identifying the application object representing TextEdit:
application "TextEdit"
document 1 of application "TextEdit"
name of document 1 of application "TextEdit"
AppleScript can evaluate these references to obtain the objects you want without any
further information.
A relative reference, on the other hand, doesn’t specify the root object. For example,
these expressions will all be treated as relative references:
name of document 1
document 1
name
Because AppleScript can’t resolve a reference unless it knows where to begin its
search, it assumes that any relative reference must be part of a larger reference. To find
the missing piece of the reference, it looks at the current default target of the script.
Initially, the default target is the script itself, but as we discussed in the earlier
“Understanding Commands” section, you can use tell blocks to define a new default
target for statements within the block. For example:
-- The default target is initially the current script
tell application "TextEdit"
-- The default target is now application "TextEdit"
tell document 1
-- The default target is now document 1 of application "TextEdit"
name
end tell
-- The default target here is application "TextEdit"
end tell
-- The default target here is the current script
When AppleScript evaluates the name expression, it knows that this is the name of a
property in an application object, so it uses the enclosing tell blocks to expand this
into a full reference: name of document 1 of application "TextEdit". Once AppleScript
has assembled the full reference, it can decide what to do with it (in this case, get the
value of the property from TextEdit).
A word of warning when using nested tell blocks: sometimes applications use the
same names for both properties and classes—for example, TextEdit has both a text
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
97
property and a text class. If AppleScript encounters the text keyword by itself, it will
assume you are using text as the name of a class, not a property, and return the class
name, text:
tell application "TextEdit"
tell document 1
text
end tell
end tell
--> text -- This is not what you wanted!
In this situation, you need to modify your code to make it clear to AppleScript that you
are using text as a property name within a larger reference, like this:
tell application "TextEdit"
text of document 1
end tell
Or, like this:
tell application "TextEdit"
tell document 1
text of it
end tell
end tell
--> "Hello, World!" -- Much better!
NOTE: it is a special AppleScript variable that always contains a reference to the target of the
current tell block. You will learn more about this and other special variables in Chapter 11.
Script 5–5 shows a more complex example that opens the current user’s home folder
window, repositions it, sets it to list view sorted by date, and displays the folder sizes.
(Once you know a bit more about Finder scripting, why not try rewriting this script
without any nested tell blocks, just to see what a difference they make?)
Script 5–5.
tell application "Finder"
tell home
open
tell container window
set bounds to {40, 40, 800, 800}
set current view to list view
tell its list view options -- Equivalent to: tell list view options of it
set calculates folder sizes to true
set sort column to column id modification date column
end tell
end tell
end tell
end tell
Now that you know the principles by which an application object model operates, let’s
put that knowledge to the test by exploring a real, live example: the Mac OS X Finder.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
98
CHAPTER 5: Understanding How Application Scripting Works
Exploring a Typical Object Model
A good way to get your head around object models is to dive straight in and explore
one. One of the best applications to start with is the Finder. In addition to being well
designed and not too complicated, the Finder’s GUI presents the structure of the file
system in much the same way as its scripting interface.
NOTE: Some of the following examples use file, folder, and disk names that are specific to my
computer. Before running these scripts yourself, modify them as necessary to use file, folder,
and disk names that appear on your own file system.
To begin your exploration, choose the Go ➤ Computer option from the Finder’s menu bar.
This will show a window somewhat similar to the one in Figure 5–5, displaying all of your
mounted volumes.
Figure 5–5. A Finder window that displays the currently mounted volumes
The Finder represents mounted volumes as objects of class disk, so let’s try getting all
of the disk elements of the Finder’s main application object. Figure 5–6 shows the
script and a typical result.
As you can see, the result of the script in Figure 5–6 is a list of references. The first thing
you will notice is that all but one of the references are of the following form:
disk "volume name" of application "Finder"
Each of these disk objects is identified by its name: “Bubba Ho Tep” and “Time Machine
Backup”. As long as you do not have two or more disk objects with the same name, you
can be confident that each of these references identifies a different volume in the file
system.
The one exception is the following reference:
startup disk of application "Finder"
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
99
Figure 5–6. An AppleScript that returns a list of references to the currently mounted volumes
The Finder is clever enough to know that one of the mounted volumes must be the one
you booted the operating system from, so it provides a special shortcut that allows you
to locate that volume even if you don’t know its name in advance. This shortcut takes
the form of a property named startup disk that appears in the Finder’s main
application object.
Many scriptable applications use properties like this to provide useful shortcuts to
particularly important or useful objects in their object models.
You can refer to the startup disk property in your own code like this:
tell application "Finder"
startup disk
end tell
When you run this script, the Finder returns another reference:
--> startup disk of application "Finder"
If you know the startup disk’s name, you can refer to it using that as well. For example,
my startup disk is named “Macintosh HD”, so I can refer to it by name:
tell application "Finder"
disk "Macintosh HD"
end tell
Once again, when you run the script, the result is
--> startup disk of application "Finder"
Notice that the reference returned by the application is not necessarily the same as the
one you gave it. A well-designed scriptable application will return whatever reference it
thinks will be most useful to you the next time you need to refer to a particular object.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
100
CHAPTER 5: Understanding How Application Scripting Works
Now let’s explore the file system more deeply. In Figure 5–7, I have dug down to the
Sites folder of my home folder, where I can see a document file, index.html, as well as
another folder, images.
Figure 5–7. Viewing a portion of the file system hierarchy in the Finder’s GUI
The Finder’s scripting interface also represents the file system structure as objects
nested within other objects, allowing us to dig down into it in much the same way.
From Figure 5–7, you can see that the Macintosh HD volume contains a number of
folders: Applications, Developer, Library, System, and Users. The Finder’s GUI displays
each folder as a folder icon followed by the folder’s name. Similarly, the Finder’s
scripting interface represents each folder as an object of the folder class. If you are
interested in these folders, you can use AppleScript to ask for references to all of them,
as shown in Script 5–6.
Script 5–6.
tell application "Finder"
every folder of disk "Macintosh HD"
end tell
--> {folder "Applications" of startup disk, folder "Developer" of startup disk,
folder "Library" of startup disk, folder "System" of startup disk,
folder "Users" of startup disk}
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
101
Or you can ask for just one folder in particular; for example:
tell application "Finder"
folder "Users" of disk "Macintosh HD"
end tell
Here, I am asking the Finder to look in its application object for an element of class
disk whose name is “Macintosh HD”. Once it finds that object, it should look in it for an
element of class folder whose name is “Users”.
Next, I’ll locate my home folder, named hanaan, which is in the Users folder:
tell application "Finder"
folder "hanaan" of folder "Users" of disk "Macintosh HD"
end tell
As this is where I keep all of my personal files, it is a very useful place to get to. Once
again, the Finder’s designers anticipated this and added another shortcut property,
home, to the Finder’s main application object. This allows me to get to my home folder
with much less effort:
tell application "Finder"
home
end tell
If I run the previous two scripts, both return the exact result—a complete step-by-step
reference to the object that represents my home folder:
--> folder "hanaan" of folder "Users" of startup disk of application "Finder"
NOTE: You may notice that the preceding scripts do not specify a particular command for the
application to perform using the given reference. In these cases, AppleScript will automatically
send a get command to the target application, asking it to resolve the reference for you. We will
discuss how these “implicit gets” work in Chapter 12.
Let’s build a reference to the index.html document file in the Sites folder now, taking
advantage of the home property of the Finder’s application object while we’re at it.
Script 5–7 shows the easiest way to construct this reference.
Script 5–7.
tell application "Finder"
document file "index.html" of folder "Sites" of home
end tell
Although you can refer to the same file like this,
tell application "Finder"
document file "index.html" of folder "Sites" of ¬
folder "hanaan" of folder "Users" of disk "Macintosh HD"
end tell
using the home property makes the code shorter. It also avoids any need to hard-code
the home folder and startup disk names for one particular user, making the code much
more portable.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
102
CHAPTER 5: Understanding How Application Scripting Works
TIP: A good way to see different Finder references is to select a file, folder, or disk anywhere in
the Finder’s GUI and then run the following code: tell application "Finder" to get
selection.
Let’s try a few more examples for practice. First, let’s ask for the name property of every
folder in the current user’s home folder:
tell application "Finder"
name of every folder of home
end tell
--> {"Desktop", "Documents", "Downloads", "Library", "Movies", "Music", ...}
Or, what if we want a reference to the disk or folder that is displayed in the frontmost
Finder window? Here’s how we do it (assuming the window exists):
tell application "Finder"
target of Finder window 1
end tell
--> folder "Applications" of startup disk of application "Finder"
Notice how we refer to the Finder window by numerical index. Previous examples have
identified elements by name or, by using the every keyword, all at once. However,
elements normally appear in a particular order—window elements, for example, are
ordered so that the frontmost window is window 1, the window behind it is 2, and so
on—so another option is to refer to elements by position. The target property contains
a reference to the folder that is displayed in that window.
The next example digs down into the Finder’s desktop window object to get the
coordinates of the desktop window, which is handy if you are writing a script to
reposition other Finder windows on the desktop:
tell application "Finder"
bounds of container window of desktop
end tell
--> {0, 0, 1680, 1050}
Lastly, here’s another corner of the Finder’s object model for you to consider:
tell application "Finder"
Finder preferences
end tell
--> Finder preferences of application "Finder"
Once again, we are referring to an application object property, Finder preferences, that
contains another application property. The result in this example is unremarkable—just a
fresh reference to the property itself—but dig deeper and things get more interesting.
The Finder preferences property contains a one-off object of class preferences that
can be used to get and set various Finder preferences.
For instance, the preferences object contains a property, new window target, that
contains a reference to the disk or folder that is initially displayed when you choose File
➤ New Finder Window (z+N) in the GUI:
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
103
tell application "Finder"
new window target of Finder preferences
end tell
--> startup disk of application "Finder"
This property is editable, so you can easily use a set command to change its value to a
different reference:
tell application "Finder"
set new window target of Finder preferences ¬
to folder "hanaan" of folder "Users" of startup disk
end tell
Now when I create a new Finder window in the GUI, it will initially show the contents of
my home folder instead of my startup disk.
Licensed by
Jim Kilcullen
2884260
While the Finder’s designers could have added these preferences properties directly to
the main application object, tucking them away in their own dedicated object is a bit
tidier. Incidentally, another application that likes to organize properties into
“preferences” objects is Adobe InDesign, which we’ll cover in Chapter 26. There,
though, you’ll be dealing with many dozens of properties at a time—so neatness really is
a virtue!
TIP: A great way to explore live objects in an application object model is by using Late Night
Software’s Script Debugger (http://www.latenightsw.com). Like AppleScript Editor, Script
Debugger’s Dictionary view can display class and command definitions from the dictionary.
However, it also provides a powerful expandable Explorer view, allowing you to examine the
actual objects that currently exist in the application, along with their properties and elements.
All application object models fit together according to the same basic rules, so once you
know how to navigate the object model of, say, the Finder, the same techniques will
serve you well when you go on to script other applications, from very simple
applications such as TextEdit all the way up to powerful and sophisticated applications
like InDesign.
Understanding the general rules by which application object models are put together is
essential to finding your way around those object models, but it is not the only
knowledge you require: you must also understand exactly how the objects (and
commands) in a particular application are structured. This brings us to our fourth key
concept of application scripting: how scriptable applications document these structures
in their application dictionaries.
Understanding Application Dictionaries
Every scriptable application has a scripting dictionary that defines all the application’s
commands and classes available for use with AppleScript. The dictionary supplies two
things: the keywords that AppleScript will need to compile your scripts, and some basic
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
104
CHAPTER 5: Understanding How Application Scripting Works
human-readable documentation, consisting of a short description of each command and
class, what it does, and the features it provides.
Some applications include additional information such as sample code and notes in their
dictionaries, making it easier to understand how to use them. Others may prefer to
supply this sort of information as separate documentation. Unfortunately, all too many
applications do not provide anything beyond the essential details required by the
dictionary format.
One of the challenges in learning an application’s scripting interface is learning your way
around its dictionary. Large, complicated applications such as Microsoft Word and
Adobe InDesign can have massive dictionaries to pour through, and even the
dictionaries of smaller, simpler applications such as Finder and iTunes can take a while
to understand.
To make dictionaries easier to digest, they are normally broken up into several sections,
or suites, each defining a number of classes and/or commands that share a common
purpose or are otherwise related to each other.
TIP: Remember, classes describe the structure of the objects you work with, and commands are
what you use to manipulate those objects.
For example, the Standard Suite that appears in most application dictionaries defines a
number of basic classes such as application, document, and window and sets out the
basic functionality for these features. It also defines a number of commands for
performing common operations on application objects, including creating new objects
(make), moving existing objects around the object model or making fresh copies of them
(move and duplicate), or even deleting objects completely (delete).
There are a few quirks as to how class and command information can be laid out in a
dictionary, but we’ll discuss these quirks as we go. For now, let’s dive in and start
exploring a few application dictionaries in order to understand them better. Of course, to
do this we’ll need some way to view them, so it’s time to bring up AppleScript Editor
and investigate the one big feature we skipped over in Chapter 4: the dictionary viewer.
Introducing AppleScript Editor’s Dictionary Viewer
To view an application’s dictionary in AppleScript Editor, choose File ➤ Open Dictionary,
pick the application you’re interested in, and click Open. Or, if you are in the Finder, you
can drag and drop the application you’re interested in onto AppleScript Editor’s icon
and AppleScript Editor will open its dictionary automatically.
TIP: You can add frequently used applications to AppleScript Editor’s Library palette (Window ➤
Library), allowing you to open their dictionaries quickly with a simple double-click. See Chapter 4
for more information on this feature.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
105
If the application does not have a dictionary, AppleScript Editor will display the following
message: “Unable to read the dictionary of the application or extension because it is not
scriptable.”
Even if an application does not have a dictionary, all is not lost: you can still use the
standard run, open, activate, and quit commands on it, and if you really must automate
it, then you may be able to control its GUI directly from AppleScript using GUI Scripting,
which we’ll look at later in the book. Fortunately, many applications do provide at least
some level of AppleScript support, so once you’ve established that an application is
scriptable, the next step is to read its dictionary to figure out exactly what scripting
features it provides.
For this exercise, choose File ➤ Open Dictionary, select the Finder application from the list,
and click Open to bring up its dictionary in a new viewer window. Figure 5–8 shows how
the viewer window will initially look.
Figure 5–8. Viewing the Finder’s dictionary in AppleScript Editor
The AppleScript Editor dictionary viewer window is divided into three parts: the toolbar at
the top, the navigation browser beneath it, and the main terminology view at the bottom.
The toolbar contains a number of useful controls, most of which are self-explanatory.
The most important ones are the View buttons and the Search field. The Search field is
great when you want to find a particular word: just type it in, and a list of all matching
entries will immediately appear. The View buttons let you control how the application
dictionary is displayed in the navigation browser.
The main terminology view at the bottom of the window is where the definitions of the
application’s classes and commands are displayed. We’ll discuss how to interpret the
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
106
CHAPTER 5: Understanding How Application Scripting Works
information in the next section. By default, the terminology view shows the entire
contents of the application’s dictionary, although you can use the navigation control to
narrow down what is displayed.
The navigation control beneath the toolbar provides a convenient summary of the
dictionary’s contents and also allows you to jump quickly to one particular part of the
dictionary just by selecting one or more items in each column. How the dictionary is
displayed here depends on the View mode you have selected in the toolbar. From left to
right, the three View buttons allow you to browse the dictionary by suite (the default
view), by containment, or by inheritance.
When the dictionary viewer window is first opened, you will see two things: a list of all of
the dictionary’s suites in the left column of the navigation control, and all of the
dictionary’s command and class definitions in the main terminology view. While you can
scroll the dictionary view up and down to find the entries you want, a quicker way to
navigate is by clicking the name of a suite in the navigation section. When you do this,
the terminology view shows only the classes and commands in that suite. The
navigation control also updates to show the names of the commands and classes in that
suite. Figure 5–9 shows how the dictionary viewer looks after selecting the Finder Basics
suite
Figure 5–9. Viewing the Finder Basics suite
Notice how each name is preceded by a colored icon: a square orange icon containing
the letter S indicates a suite name, command names are marked by the letter C in a blue
circle, while the letter C in a purple square tells you that you’re looking at a class name.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
107
NOTE: While most class definitions describe objects that are part of the application’s object
model, some class definitions are used to describe the structure of AppleScript record objects
instead. For instance, the print settings class in TextEdit’s dictionary actually describes a
record structure used by TextEdit’s print command. You will learn more about records in
Chapter 10.
How Classes Are Documented
In an application dictionary, a class is simply a description of all the features you can find
in a particular type of object. Early in the chapter, I explained how an application object
can have properties and, in many cases, elements as well. Let’s now look at how to find
out exactly what properties and elements are available for a particular class of objects.
The Finder Basics suite contains only three entries: two commands, copy and sort, and
the main application class. This is probably the most important class in any scriptable
application, and the one you will look at first. The reason for that is obvious: as you
learned in the previous section, every application’s object model has a single root object
whose class is application. Now that you have access to the Finder’s dictionary, you
can find out exactly what properties and elements its main application object provides.
To display only the application class definition, click the application entry in the
navigation browser, as shown in Figure 5–10.
TIP: To view more than one command or class at a time, just hold down the Shift key when
clicking in the middle column of the navigation view to make a multiple selection. (You can also
Shift-click in the other columns as well, although you can only make multiple selections in one
column at a time.)
At the top of the terminology pane is the name of the class, application, followed by the
letter n. AppleScript Editor’s dictionary viewer likes to distinguish classes (which
describe objects) and commands (which describe actions) using the letters n and v,
short for noun and verb, just like in a traditional English language dictionary.
Following the letter n is a pair of square brackets. This tells you how this class definition
relates to other class definitions in the same dictionary. We’ll discuss this further in later
sections. The line then ends with a short comment describing the class.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
108
CHAPTER 5: Understanding How Application Scripting Works
Figure 5–10. Viewing the application class
You’ll also notice that the right column in the navigation pane now lists the names of all
the properties and classes defined by the class. Properties are indicated by purple
squares containing the letter P, and elements are indicated by orange squares
containing the letter E. Clicking the name highlights the corresponding line in the main
terminology pane.
NOTE: Calling object classes “nouns” and commands “verbs” in the dictionary viewer makes
some sense; after all, in human languages, nouns are the names of objects, while verbs are the
names of actions you can perform on those objects. However, the technical terms class, object,
and command are more precise in their meaning, so we will stick with them for the rest of the
book.
Viewing the Properties and Elements Defined by a Class
Under the section labeled PROPERTIES, you will see a list of property names, each one
highlighted in bold. Each property name is followed by a pair of parentheses. This tells
you the class of object the property contains, and may also contain r/o to indicate that
the property is read-only. Finally, there is short description of the property’s purpose.
For example, you can see from Figure 5–10 that the Finder’s application class has a
name property containing an object of class text; that is, an AppleScript string. Further
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
109
down, you can see that it has a property named home containing an object of class
folder. (Technically, the home folder contains a reference to an object of class folder,
but that’s a minor distinction we won’t worry about here.) This time, the class name is
displayed as a blue underlined link. Clicking this link takes you directly to the definition
of the Finder’s folder class, where you can learn about the structure of folder objects,
including any properties and elements that they have.
The ELEMENTS section lists the names of the application object’s elements. Each
element name corresponds to the name of an application-defined class; the only
difference is that the dictionary viewer normally uses the plural version of the class
name. Each element name is displayed as a blue underlined link, allowing you to jump
directly to the class in question just by clicking it.
For example, disks are listed as one of the elements of the application class definition,
which tells you that the Finder’s main application object can contain any number of
objects of class disk. Clicking the disks element name takes you directly to the
description of the disk class.
TIP: See the “Introducing Object Properties” and “Introducing Object Elements” sections earlier
in the chapter for more discussion of properties and elements.
How Inheritance Describes Features Shared Between Classes
So far, we’ve looked at how the application class is documented in the Finder’s
dictionary. This is quite an easy class to read, as all of its properties and elements are
listed in the one place (except for the old desktop picture property, which is tucked
away in the Legacy suite). Many classes take a bit more work to understand, however.
For example, let’s consider how the Finder’s folder class is documented.
First, click the Finder’s Containers and Folders suite in the navigation section of the
dictionary viewer to bring up a list of all classes in the suite. Next, click the folder class
to view its definition, as shown in Figure 5–11.
How strange—you can see the description of the folder class, but there doesn’t seem
to be anything in it! Surely a folder object must have some properties and elements?
The answer to this riddle lies in the first line of the class definition, inside the square
brackets, where it says inh. container > item. The “inh.” part is short for inheritance,
and what this means is that some (or all) of the folder class’s properties and elements
actually come from another class in the Finder dictionary. In this case, the folder class
inherits a number of its attributes from the container class (which in turn inherits some
of its attributes from the item class).
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
110
CHAPTER 5: Understanding How Application Scripting Works
Figure 5–11. Viewing the folder class definition in the Finder’s dictionary
Okay, then, let’s look up the container class to see what we’re missing. Click the
container link to bring up the class definition, shown in Figure 5–12.
Figure 5–12. Viewing the container class definition in the Finder’s dictionary
That’s more like it—now we can see what types of elements a folder object can have.
We can also see some of the properties you’d expect to find in a folder object, though it
still looks like we’re missing a few.
No problem: according to the first line of the class definition, the container class inherits
in turn from the class named item, so click that link to bring up the item class definition,
as shown in Figure 5–13.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
111
Figure 5–13. Viewing the item class definition in the Finder’s dictionary
The item class doesn’t inherit from any other classes, which means at last we’ve found
the rest of the properties available in folder objects.
The container and item classes are interesting cases. Unlike the folder class, which
describes the folder objects you work with in your scripts, the container and item
classes do not describe actual objects in the Finder’s object model. Instead, they are
defined solely as a foundation for other classes, such as folder, to build on.
You may be wondering why the Finder’s designers would go to all of this trouble,
instead of sticking everything into the folder class. Well, the reason is simple: many of
the basic properties of a folder object can also be found in other types of Finder objects,
such as disks and document files. Every disk, folder, and document file in the file system
has a modification date, for example, so rather than write the modification date
property three times—once in the disk class, once in the folder class, and again in the
document file class—and then doing the same for all of the other properties they have
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
112
CHAPTER 5: Understanding How Application Scripting Works
in common, it makes much more sense to document all of these properties in a separate
class, item, and then indicate that the disk, folder, and document file classes all
possess the properties listed in the item class (plus any additional properties that they
define for themselves).
Similarly, some (though not all) file system objects, such as disks and folders, can
contain other objects as elements. To better organize the dictionary, the Finder’s
designers have created another class, container, that defines all the attributes from
which any file system object that contains other file system objects can inherit.
Now that you know how to find out all the properties and elements for one particular
class, let’s step back and take a look at the Finder’s inheritance hierarchy in full. Figure
5–14 provides an overview of all the classes defined in the Finder dictionary, showing
which classes inherit from which.
item
application
file
container
window
Finder
window
information
window
process
preferences
window
clipping
window
application
process
KEY
class
name
A class that describes objects
that appear in the object model.
class
name
A class whose only purpose is to
define properties and elements
used by other classes.
desk accessory
process
desktop
window
A
Inheritance is indicated by an
arrow. In this example, class A
inherits from class B.
preferences
icon view
options
column view
options
list view
options
B
column
alias list
Figure 5–14. The Finder’s complete class inheritance hierarchy
TIP: When viewing a class definition in the dictionary viewer, you can include all of its inherited
properties and elements by checking the “Show inherited items in dictionary viewer” option in
the General panel of AppleScript Editor’s Preferences window.
In addition to making the dictionary more compact by avoiding unnecessary repetition, a
careful study of class inheritance also tells you which behaviors different classes of
objects will have in common. For instance, if you know the item class defines name,
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
113
comment, and label properties, then you know that all disk, folder, and file objects will
contain these properties.
Understanding inheritance is also valuable when referring to the elements of an object.
For example, if you ask for every file element of a folder object, you will get a list of
references identifying all of the alias files, application files, document files, internet
location files, and clippings contained by that folder:
tell application "Finder"
get every file of folder "Pictures" of home
end tell
--> {document file "9781430223610.gif" of folder "Pictures" ...,
alias file "iChat Icons" of folder "Pictures" ...,
document file "iPhoto Library" of folder "Pictures" ...}
Licensed by
Jim Kilcullen
2884260
You can narrow this request by picking an element class that is further down the
inheritance hierarchy; for instance, asking for the folder object’s document file elements
will return references to objects of class document file only:
tell application "Finder"
get every file of folder "Pictures" of home
end tell
--> {document file "9781430223610.gif" of folder "Pictures" ...,
document file "iPhoto Library" of folder "Pictures" ...}
Or you can broaden this request by asking for the container’s item elements. This will
give you references to all of its disks and folders as well as all of its files:
tell application "Finder"
get every file of folder "Pictures" of home
end tell
--> {folder "New Artwork" of folder "Pictures" ...,
folder "Unsorted Images" of folder "Pictures" ...,
document file "9781430223610.gif" of folder "Pictures" ...,
alias file "iChat Icons" of folder "Pictures" ...,
document file "iPhoto Library" of folder "Pictures" ...}
A useful, if not always reliable, feature of AppleScript Editor’s dictionary viewer is the
ability to browse classes according to their inheritance hierarchy. To do this, click the
right View button in the toolbar, as shown in Figure 5–15.
Unfortunately, the dictionary viewer is a bit limited in that it only shows classes that
ultimately inherit from the item class, and only then if the item class is actually visible in
the dictionary. Hopefully, this shortcoming will be fixed in a future release, but it may
work well for some applications and can help you to develop a feel for the way that
inheritance works.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
114
CHAPTER 5: Understanding How Application Scripting Works
Figure 5–15. Viewing the inheritance hierarchy for Finder’s alias file class
CAUTION: Don’t confuse the inheritance hierarchy with the containment hierarchy. Inheritance
tells you what features objects have in common; containment tells you which classes of objects
can be nested inside which other classes of objects.
Class Definitions Can Be Spread Across More than One Suite!
Returning to the top line in the application class description (refer to Figure 5–10), you
will see a note telling you to look in the Legacy suite, so click the Legacy suite link to
jump directly there.
As you can see from Figure 5–16, it’s not just the Finder Basics suite that defines a class
named application; the Legacy suite lists an application class as well!
You might be wondering how a scriptable application can have two different classes
with the same name. In fact, there is still only a single application class in the Finder;
however, its definition has been split into two parts—one appearing in the Finder Basics
suite and the other in the Legacy suite.
Many applications take this slightly odd approach to documenting classes. For example,
Cocoa-based applications such as TextEdit and Mail often list the features of
application and document classes that exist in all Cocoa applications in their Standard
Suites. Features that are only found in that particular application are then listed in a
separate suite—for example, most of the definition for Mail’s application class appears
in its Mail suite, along with other Mail-only features.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
115
Figure 5–16. The Legacy suite contains a second application class definition!
This habit of splitting some class definitions across several suites is usually more
accidental than deliberate. It is most common in Cocoa applications, an odd side effect
of the way that Mac OS X’s Cocoa Scripting system is designed.
In the Finder, though, splitting the application class’s definition was a deliberate
decision. The Legacy suite lists features that were originally added to the Finder in the
pre–OS X days but have since moved to OS X’s own dedicated System Events
application. These features still work in the Finder, though Apple does recommend that
you use System Events (which you’ll learn about in Part 3) instead.
NOTE: Cocoa Scripting is the name of the framework that provides all Cocoa-based applications
with much of their AppleScript support (and a few quirks too).
Now that you know how to discover the properties and features provided by objects,
let’s look at how you can explore an application’s containment hierarchy using the
dictionary viewer.
Browsing the Containment Hierarchy
Let’s play a little more with the dictionary viewer’s navigation options. You’ve already
seen how to browse classes by suite and by inheritance. Now let’s try exploring classes
according to containment structure.
To switch the navigation pane to the containment view, click the middle View button in
the toolbar. When you do this, the navigation section changes from displaying classes
and commands by suite to displaying the application class in the leftmost column.
(Actually, you will see two “application” entries—this is due to one of the quirks I hinted
at earlier, but don’t worry about it for now.)
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
116
CHAPTER 5: Understanding How Application Scripting Works
Now you can browse the application dictionary according to the elements of each class.
Each time you click a class name that has an arrow to its right, a new column appears
listing the classes of its elements. Take a look at Figure 5–17 to see what I mean.
Figure 5–17. Browsing the Finder’s dictionary by its containment hierarchy
In Figure 5–17, I started by clicking the application entry with the arrow next to it, which
gives me a list of all the classes of elements the Finder’s application object can have.
Let’s say I want to build a reference to a document file, starting with the disk it is on, so I
click the disk entry in the second column. That shows me all the classes of elements a
disk object can have; I figure the file is probably in a folder, so I click folder next…and
so on, until I click the document file entry, which doesn’t have any elements of its own.
One disadvantage of the dictionary viewer’s containment view is that it only lists the
elements defined by each class; it does not include any properties that contain
references to other application objects, such as the Finder’s startup disk and home
properties. It also gets a bit confused when the same class name appears in different
suites (this is why there are two application entries shown in Figure 5–17, for example).
Still, even with these shortcomings, it can be a useful tool when you’re trying to
understand how an application’s object model is laid out.
Another option is to draw your own containment diagram as you read through the
dictionary. This is a bit more work, but it’s a good way to learn. The diagram in Figure
5–18 describes the main part of the Finder’s containment hierarchy.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
117
application
startup disk
home
items
desktop
containers
items
trash
files
folders
containers
folders
items
disks
files
alias files
alias files
containers
application
files
application
files
document
files
document
files
files
folders
internet
location files
windows
internet
clippings
location
files
internet
location files
internet
clippings
location files
Finder
windows
packages
target
packages
KEY
Some classes of application
objects can contain other
application objects.
property
name
A straight connecting line
indicates a property that
contains another object.
element
name
A “crow’s foot” connecting
line indicates objects that
appear as elements.
Dotted lines indicate parts of the
containment hierarchy omitted
for simplicity, space, or because
they already appear elsewhere.
Figure 5–18. A diagram of the Finder’s containment hierarchy
At the top is the main application object. The next row shows the contents of the
application object. On the left are properties that contain other application objects; on
the right are its elements. (Some of the less important properties and elements are
omitted for space.)
The most important elements of the main application object are the disk elements, so I
have expanded on that part of the diagram to show most of the elements that an object
of class disk can have, and so on.
You’ll notice that I’ve used dotted lines to indicate where parts of the diagram have been
omitted. For instance, folder objects can contain other folder objects, which can contain
other folder objects, and so on indefinitely, so I’ve truncated that bit for obvious reasons.
The home property of the main application object contains a folder object, but as the
containment structure for folders is already shown elsewhere in the diagram I’ve not
repeated it. Less interesting classes of objects, such as clippings and packages, have
been left out as well. The art of drawing a good containment diagram is to include
enough information to give you a feel for its structure, but not so much that it becomes
impossibly complicated to follow.
You’ll also notice that the connecting lines to properties and elements are different.
Since each property only appears once in an object, I have indicated this one-to-one
relationship with a straight line. On the other hand, a single object can have any number
of elements—one, many, or even none at all—so the connecting lines end in crow’s feet
to indicate this one-to-many relationship. (Incidentally, I borrowed this notation from the
world of database programming, which is also where the inventors of AppleScript took
some of their ideas from.)
Finally, I have written the names of some elements in italics. That is to remind me that
asking for these elements will return references to several different classes of objects.
For instance, asking for, say, file elements will return objects of class alias file,
application file, document file, and so on, whereas asking for document file
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
118
CHAPTER 5: Understanding How Application Scripting Works
elements will return objects of class document file only. Refer to the earlier section on
inheritance for more details on this aspect of scriptable application behavior.
CAUTION: Don’t confuse the containment hierarchy with the live object model. The containment
hierarchy only tells you how to reach different classes of objects. To find out exactly what objects
your application currently contains, you need to send lots of get commands to the running
application and see what comes back, or use Script Debugger’s Explorer view, which does this
for you.
How Commands Are Documented
An application’s dictionary will describe all of the commands that the application
recognizes. Some applications define relatively few commands that are widely used on
many different classes of objects. Others provide lots of specialized commands to
perform different tasks. Well-designed applications tend to follow the first approach,
although it does depend to some extent on the type of application.
Most scriptable applications include a Standard Suite, which is one of the recommended
suites provided by Apple. The Standard Suite contains commands for creating and
deleting objects, and moving them around the object model. These commands are usually
similar from application to application. Other suites may contain commands that are
unique to that particular application. For example, the Finder Items suite in the Finder’s
dictionary includes an empty command for emptying the Finder’s Trash.
As we discussed earlier, a command is made up of a name followed by any number of
parameters. Figure 5–19 shows the definition for the Finder’s move command.
Figure 5–19. Viewing the move command definition in the Finder’s dictionary
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
119
The first line starts with the command’s name, move, followed by the letter v, which is
short for “verb.” That tells you that you are looking at the definition of a command.
(Remember, AppleScript Editor’s dictionary viewer likes to refer to objects as nouns and
commands as verbs.) This is followed by a short description of what the command
does. In this case, the move command is used to move one or more objects from their
original position in the object model to a new location.
The rest of the definition tells you how to write the command in your script. Naturally,
you begin with the command’s name, move. The move command requires a direct
parameter, which is a reference to the object, or objects, that you wish to move. In the
dictionary, the class of the direct parameter is shown immediately after the command
name—in this case, it is specifier. (AppleScript Editor’s dictionary viewer uses the term
“specifier” to mean “reference.”) Following this is a colon (:), which indicates that the
rest of the line is a brief description of the parameter’s meaning.
For example, if you wish to move every document file on the current user’s desktop, you
would use the reference every document file of desktop as the move command’s
direct parameter.
Many application commands take a direct parameter, This is often a reference to the
object (or objects) you wish to manipulate.
The next parameter that the Finder’s move command requires is the location where the
object(s) should be moved to. This parameter is given as a labeled parameter, named
to. A dictionary-defined command can have at most a single direct parameter, but it can
have any number of labeled parameters. In the dictionary, the parameter name is
followed by the class of the object you need to use. The to parameter requires a
reference to the point where the objects should be moved to, which the dictionary
describes as a location specifier (a reference to the point where the object/s will be
inserted).
For example, if you want to move your document files from the desktop to the Documents
folder, the value of the to parameter would be folder "Documents" of home.
The move command has one direct parameter and four labeled parameters in total,
although only the direct and to parameters are required. The dictionary indicates which
parameters are optional by surrounding them in square brackets. You can supply values
for these parameters if you want, or you can leave them out of your command, in which
case the application will use their default values instead.
Here is how the assembled command looks:
move every document file of desktop to folder "Documents" of home
Of the three optional parameters that the move command accepts, the most useful one is
the replacing parameter. Although the dictionary isn’t helpful enough to tell you itself,
once you start using the Finder’s move command, you will soon find out that its default
value is false. In other words, if you try to copy a file or folder to a location where
another file or folder of the same name already exists, the move command will generate
an error telling you that it is not allowed to replace that item. If you want the Finder to
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
120
CHAPTER 5: Understanding How Application Scripting Works
overwrite any existing files or folders of the same name, you will have to specify your
own true value for the replacing parameter.
NOTE: When compiling a script, AppleScript may reformat Boolean parameters for readability.
For instance, move some_item to new_location replacing true will compile as move
some_item to new_location with replacing. More on this in Chapter 12.
If the command returns a result, the last line of the command’s definition indicates the
class of the value returned—in this case, a new reference (specifier), followed by a
brief description.
Now that you’ve learned how to read application dictionaries, let’s discuss the things
that they don’t tell you.
Application Dictionaries Don’t Tell You Everything!
Although dictionaries are an essential part of application scripting, they are often not as
good as they could or should be. Some dictionaries may simply be buggy or broken.
Others may be poorly thought out, inventing nonstandard commands for tasks that
could be performed using the standard set of application commands, or duplicating lots
of properties across multiple classes instead of establishing a good, clean inheritance
structure between these classes.
However, even well-designed dictionaries rarely provide all of the information you need
to script applications effectively. This is partly the fault of the dictionary format itself: the
original AETE (“Apple Event Terminology Extension”) format was very limited in the kinds
of information it could contain, and even the newer SDEF (“Scripting Definition”) format
does not force application developers to document every detail.
The best application developers supply additional documentation and examples, either
included in the optional sections of an SDEF-based dictionary, or as separate files on
their websites. Microsoft and Adobe are particularly good at this, for example.
Other applications provide only the basic dictionary, leaving you to figure out the
missing details for yourself. (Surprisingly, this includes quite a few Apple applications.)
NOTE: A lack of good documentation can make learning to script applications something of a
challenge. If you find an application’s scripting documentation to be inadequate, don’t be afraid
to contact the application developer with a polite request for improvements.
One of the biggest challenges for application scripters is working out which classes of
objects can be used in which commands. For instance, although the Apple iTunes
dictionary will reveal the make command and the track class, iTunes doesn’t allow you to
combine the two to create a new track object. Thus, a command such as the following,
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
121
although it looks as though it ought to work correctly, will just generate an error when
you run it:
tell application "iTunes"
make new file track at playlist 1 with properties ¬
{location:alias "Macintosh HD:Users:hanaan:Music:some.mp3"}
end tell
-- iTunes got an error: Can't make class file track
Fortunately, there are ways to create and copy tracks in iTunes, although you’ll have to
wait until Chapter 21 to find out how.
Similarly, the Finder dictionary contains the class window and the command duplicate,
but that doesn’t mean you can duplicate a window. (You can, however, use the make
command to create a new window that displays the contents of the desired folder or
disk.)
Some class definitions may include a RESPONDS TO section that tell you which
commands accept objects of this class as their direct parameter, but many dictionaries
do not provide this information. Even in those that do, this section may not list every
command that can be used.
Labeled parameter descriptions can be even more vague. For instance, the to
parameter in the Finder’s move command requires an insertion location reference, but
doesn’t say exactly how this reference should be constructed. As you gain experience in
application scripting, you will develop a good idea of what tends to work and what
doesn’t. We’ll discuss some of the approaches you can try later, in Chapter 12.
While figuring out the correct parameters to commands is usually the greatest challenge,
even simple features like properties may require some investigation.
Consider the container property defined by the Finder’s item class, or the entire
contents property defined by the container class. Although I didn’t include them in the
earlier containment diagram (refer to Figure 5–18), these properties do contain
references to other Finder objects and can be extremely useful for certain tasks. The
container property gives you a reference to the folder or disk that contains a file or
folder object. The entire contents property allows you to refer to all of the files and
folders within a disk or folder, no matter how deeply nested they are (though in practice,
it’s best used on small segments of the file system, as it becomes impossibly slow with
large numbers of items).
The challenge of the container and entire contents properties is that the Finder
dictionary does not tell you very much about the values they contain. Each property
claims to contain a value of class specifier—that is, a reference—but doesn’t say what
sort of object (or objects) it refers to. With the container property, it is reasonable to
guess that if your object is a file or folder, the container property will contain a reference
to an object of class folder or disk. The entire contents property is less obvious,
however.
One way to find out is to perform some tests. For instance, the following scripts confirm
the nature of the container property:
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
122
CHAPTER 5: Understanding How Application Scripting Works
tell application "Finder"
container of home
end tell
--> folder "Users" of startup disk of application "Finder"
tell application "Finder"
container of folder "Users" of startup disk
end tell
--> startup disk of application "Finder"
When you ask for the contents of the entire contents property, the result is a list of
references, like this:
tell application "Finder"
get entire contents of folder "Pictures" of home
end tell
--> {folder "Holidays June 2009" of folder "Pictures" of folder "hanaan"
of folder "Users" of startup disk of application "Finder",
document file "9781430223610.gif" of folder "Pictures" of folder "hanaan"
of folder "Users" of startup disk of application "Finder",
alias file "iChat Icons" of folder "Pictures" of folder "hanaan"
of folder "Users" of startup disk of application "Finder",
document file "iPhoto Library" of folder "Pictures" of folder "hanaan"
of folder "Users" of startup disk of application "Finder",
document file "005.jpg" of folder "Holidays June 2009"
of folder "Pictures" of folder "hanaan" of folder "Users"
of startup disk of application "Finder",
document file "007.jpg" of folder "Holidays June 2009"
of folder "Pictures" of folder "hanaan" of folder "Users"
of startup disk of application "Finder", ...}
Does this mean the entire contents property contains a list of single file references?
The answer is: no. Once again, this is a case of the Finder returning the value that it
thinks you want, which is not necessarily the value that is actually there. In fact, the
entire contents property contains a multi-item reference. If you get the property
directly, the Finder guesses that you want a list of references to the individual items and
returns that. Because the property contains an application object reference, though, you
can go further into the object model if you want. For example, Script 5–8 shows how to
narrow your request if you are only interested in document files, while Script 5–9 goes
even further, by retrieving only the file names.
Script 5–8.
tell application "Finder"
get every document file of entire contents of folder "Pictures" of home
end tell
--> {document file "9781430223610.gif" of folder "Pictures" of folder "hanaan"
of folder "Users" of startup disk of application "Finder",
document file "iPhoto Library" of folder "Pictures" of folder "hanaan"
of folder "Users" of startup disk of application "Finder",
document file "005.jpg" of folder "Holidays June 2009"
of folder "Pictures" of folder "hanaan" of folder "Users"
of startup disk of application "Finder",
document file "007.jpg" of folder "Holidays June 2009"
of folder "Pictures" of folder "hanaan" of folder "Users"
of startup disk of application "Finder", ...}
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
123
Script 5–9.
tell application "Finder"
get name of every document file of entire contents of folder "Pictures" of home
end tell
--> {"9781430223610.gif, "iPhoto Library", "005.jpg", "007.jpg", ...}
You can even manipulate all of these object directly using other commands such as set
and move. For example, to set their label colors:
tell application "Finder"
set label index of every document file of ¬
entire contents of folder "Pictures" of home to 7
end tell
The amount of control that is available through such a humble-looking property is
impressive, although you would hardly guess this from its dictionary definition, and even
experimenting for yourself may not give you the full story.
Licensed by
Jim Kilcullen
2884260
Given the limitations of application dictionaries and frequent lack of supplementary
documentation, you should also make a point of studying scripts written by other
AppleScript users, lots of which are available online, and reading the AppleScript mailing
lists and bulletin boards for valuable insights and tips. You’ll also find that as you grow
more experienced, you will become better at guessing the sort of things that are most
likely to work for a particular application, based on what you’ve found to work (or not
work) on others.
Now that we’ve discussed the four key concepts of application scripting, let’s proceed
to fill in some of the finer details, beginning with AppleScript’s application objects.
More on application Objects
As you now know, an application object model consists of objects that contain other
objects, which in turn contain yet more objects, and so on. The result is a tree-shaped
structure that starts from a single point and then branches out repeatedly until every
scriptable object within the application appears somewhere within that structure.
The base of this object tree is always represented by an object of class application.
Let’s now look in detail at how these application objects work.
Creating application Objects
Obviously, the first thing you need to know is the name of the application you want to
talk to—for example, Finder, iTunes, or TextEdit. However, having the name of an
application alone is not sufficient; if it was, you could just write code like this:
tell Finder to get name of startup disk
If you do that, though, you will get an error, as AppleScript won’t understand what you
mean by Finder. (As you will find out in later chapters, what you have there is a variable
named “Finder”, which is not what you need here.)
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
124
CHAPTER 5: Understanding How Application Scripting Works
You must be a lot more specific, and tell AppleScript in absolutely precise terms that
what you want is an object that represents the Finder application. To do this, you must
tell AppleScript to construct an application object for you.
Identifying Applications by Name
In AppleScript, an application object is represented by the keyword application,
followed by (in most cases) the name of the application written in double quotes, like
this:
application "Finder"
application "iTunes"
application "TextEdit"
The application keyword indicates the kind of object we want to create, which is (you
guessed it) an object of class application.
The double quotes are used in AppleScript source code to indicate the beginning and
end of an AppleScript text object, or string. The strings shown here represent the names
of applications we’re interested in talking to: Finder, iTunes, and TextEdit.
Put these two simple structures together—the application keyword followed by a
string—and we have a new structure called an object specifier, so called because it
identifies, or specifies, the exact object we want.
CAUTION: Be aware that AppleScript always uses the application’s default English name, even
on non-English systems.
Identifying Applications by Path
Identifying applications by name is the most commonly used approach, but it is not the
only way. You can also specify applications by their full path, like this:
application "Macintosh HD:Applications:FileMaker Pro 10:FileMaker Pro.app"
The path is a string consisting of the name of the volume, followed by the names of any
folders, and finally the full name of the application itself.
The main disadvantage of that approach is that, because the exact location of the
application is hard-coded in the script, the code is not as portable: other Macs may use
different names for their startup disks. All the same, it can come in very useful if you
have several applications with the same name and need to specify one of them in
particular.
Identifying Applications by Bundle ID
In Mac OS X 10.5 and later, you can also identify applications using their bundle
identifier, which is basically an Internet domain–style name written backward. For
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
125
instance, Apple own the apple.com domain, so its applications use bundle IDs beginning
with com.apple followed by the application name (written without spaces or other funky
characters, of course). Examples include com.apple.Finder, com.apple.iTunes, and
com.apple.TextEdit.
To create an application object using a bundle ID, you need to use a slightly fancier
version of the application specifier, consisting of the application keyword followed by
an id keyword, followed by a case-insensitive string containing the bundle ID, like this:
application id "com.apple.Finder"
application id "com.apple.iTunes"
application id "com.apple.TextEdit"
The main advantage of using bundle IDs is that, unlike an application file name, which
anyone can change at any time, the bundle ID is stored safely within the application
itself—and once an application has been assigned a bundle ID, it normally keeps that ID
for life. This makes it a very reliable way to identify a particular application.
For example, some applications such as Adobe Photoshop like to alter their file names
to reflect each new version that comes out. So a script that refers to application
"Adobe Photoshop CS3" won’t automatically recognize Adobe Photoshop CS4 if you
have that installed. However, if you refer to it using application id
"com.adobe.photoshop" then it will work regardless of what version you have installed,
as all versions of Photoshop have the same bundle ID.
NOTE: Occasionally, different versions of an application will use different bundle IDs. For
example, the new QuickTime Player X in Snow Leopard has the ID
com.apple.QuickTimePlayerX, while the older QuickTime Player 7 (which has a different
scripting interface) uses com.apple.quicktimeplayer. This can be handy if you have both
versions installed on your Mac, as you can use an application id ... specifier to target the
one you want.
Identifying Applications by Remote URL
There is one other way you can identify scriptable applications from AppleScript: by
eppc:// URL. When Mac OS X’s Remote Apple Events feature is enabled, eppc:// URLs
can be used to control applications that are running on a completely different machine!
This is a very cool feature but it’s not something you are likely to need straightaway, so
we’ll skip it for now and come back to it later, in Chapter 12.
TIP: If you write app instead of application in your code, AppleScript will expand it for you
when the script is compiled.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
126
CHAPTER 5: Understanding How Application Scripting Works
The Standard Properties of application Objects
In addition to any properties and elements defined by the application dictionary,
application objects come with several useful properties already built in: class, name, id,
version, running, and frontmost.
The class property contains the name of the object’s class. Its value is always
application (which, like all class names, is an object of class class):
class of application "Finder"
--> application
The name property contains the name of the application; for example:
name of application id "com.adobe.photoshop"
--> "Adobe Photoshop CS4"
The id property contains the bundle ID of the application; for example:
id of application "iTunes"
--> "com.apple.iTunes"
The version property contains a piece of text representing the application’s version
number; for example:
version of application "Chess"
--> "2.4.1"
The running property contains one of two values, true or false, that tells you whether or
not the application is currently running; for example:
running of application "Finder"
--> true
Lastly, the frontmost property tells you whether or not the application is the active
application in your Mac’s GUI. Its value is also one of true or false.
All of the properties are read-only; that is, you can get their existing values, but you
cannot set them to different values yourself. Only AppleScript can change their values;
for example, the value of the running property will change when an application launches
or quits.
One advantage of using these properties is that AppleScript does not have to launch the
application in order to obtain their values. For example, if you would like to tell iTunes to
start playing only if it is already running, you can use the following script:
tell application "iTunes"
if running then
play
end if
end tell
Here, the tell ... end tell block identifies the application object for iTunes as the
current target for any commands. The second line gets the value of the application
object’s running property. If the value is true, it executes the code inside the if ... end
if block—in this case, a simple play command. On the other hand, if the value of the
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
127
running property is false, then the if ... end if block (which is also known as a
conditional statement) does nothing.
Another benefit of these built-in properties is that even if the application itself is not
scriptable (such as the built-in Chess application, shown previously), you can still use
these properties to get some basic information about it.
NOTE: Except for the standard class property, these built-in properties are only available in
Mac OS X 10.5 and later. Older versions of AppleScript do not provide these application
object properties as standard; however, many scriptable applications define their own name and
version properties in their dictionaries, and you can always use Mac OS X’s invisible System
Events application to find out if they are running or frontmost. The new built-in properties are
definitely more convenient, however.
How AppleScript Compiles tell application ... Blocks
AppleScript has one more trick up its sleeve when it comes to application objects and
tell blocks. As you know, each scriptable application you deal with defines its own set
of keywords for scripts to use. For AppleScript to compile a script successfully, it needs
to know what each of the keywords used in your code means.
So how does it know which dictionary to look in each time it encounters an applicationdefined keyword? The solution is clever, yet simple: whenever AppleScript encounters a
tell block whose target is an application object, it uses the application ... specifier
to determine the application dictionary it should use when compiling keywords within
the tell block.
Normally, when we write application object references, we start with a tell application
... block, like this:
tell application "TextEdit"
every paragraph of text of document 1
end tell
In theory, you can write the same reference as follows, without any tell blocks:
every paragraph of text of document 1 of application "TextEdit"
The catch here is that this code will only compile if AppleScript recognizes all of the
keywords used without any help from the application dictionary. Fortunately for the
preceding reference, AppleScript defines a number of application-related keywords by
default—paragraph, text, and document. Other keywords will not be understood without
help from an enclosing tell application ... end tell block. For instance, try to
compile the following line in AppleScript Editor:
every document file of desktop of application "Finder"
The problem here is that the keyword document file means nothing to AppleScript, so a
compilation error occurs: “Expected ‘from’, etc. but found class name.” The exact
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
128
CHAPTER 5: Understanding How Application Scripting Works
wording is often unhelpful, but the general meaning is clear. Rearrange the Finderrelated keywords so that they appear within a tell application "Finder" ... end
tell block, and the code compiles as intended:
tell application "Finder"
every document file of desktop -- This line compiles correctly
end tell
TIP: There is another way to persuade AppleScript to compile keywords outside of a tell
application ... end tell block: the using terms from statement. This statement
comes in handy when you need to compile application-defined keywords outside of a tell
block, or where the application name can only be determined when the script is run; for instance,
application ("Adobe InDesign CS" & version_number). We’ll discuss this further in
later chapters.
Now that you know the ins and outs of identifying applications, let’s move on to examine
in depth the many different ways in which you can construct references to objects within
those applications.
More on Constructing References
As you know, a key part of application scripting is constructing references to the object
(or objects) within the object model that you want a command to manipulate. If you can’t
point to the right object, your script will not function as expected, if at all.
The different ways of pointing to an object are called reference forms. The simplest
reference form identifies a property of an object.
There are a number of reference forms for identifying an object’s elements. A single
element may be specified in any of the following ways:
By index (either a numerical value or one of several keyword options)
By name, if it has one
By unique ID, if it has one
By its position relative to (that is, before or after) another element
Multiple elements may be specified as follows:
By range
By test condition (also known as a whose clause)
All of them (using the every keyword)
In addition, when creating, copying, and moving objects, you can also refer to a point
before, after, or in between existing elements when you want to specify a location where
the object should be inserted.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
129
TIP: Multi-item references can be extremely powerful when used in application commands that
know how to process them, allowing you to manipulate many objects using a single command.
The following sections will help you understand the different reference forms and how to
use them.
Referring to Properties
Properties are easy to refer to: just write the name of the property you want, and when
the script is run, the application will locate the object stored in that property.
Here are some examples for you to try:
tell application "Finder"
selection
end tell
tell application "iTunes"
name of current track
end tell
tell application "Adobe InDesign"
properties of document preferences of active document
end tell
Referring to Elements
Whereas referring to a property is as simple as adding the property name to your
reference, referring to an element or elements of an object is a more complex, two-part
process. Not only do you have to specify the class of elements you want, you also have
to tell the application how to identify the element or elements of that class that you are
interested in.
NOTE: Remember, you can use your knowledge of the application’s inheritance hierarchy to
identify objects that belong to several related classes or that belong to a single class only. For
instance, in the Finder, referring to item elements of a specific folder encompasses all items
including folders, files, applications, and so on. Referring to the folder’s file elements narrows
the request to file objects only, and you can go further still by referring to a specific class of file,
such as document file.
The following sections look at the different ways in which you can identify the element or
elements that you want, based on characteristics such as the order in which they appear
within an object, their names, unique IDs, whether their properties and elements meet
certain conditions, and so on.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
130
CHAPTER 5: Understanding How Application Scripting Works
Identifying All Elements
In many situations, you will want a reference to all the elements of a particular object,
such as all paragraphs of a TextEdit document, all files of a folder in the Finder, or all
pages of an InDesign document.
To indicate a reference to all elements, you use the keyword every, followed by the
name of the class of elements you want:
every element_name of some_object
Here are some examples:
tell application "Address Book"
every person
end tell
tell application "Finder"
name of every folder of home
end tell
tell application "TextEdit"
every word of text of every document
end tell
Alternatively, you can omit the every keyword and use the plural class name instead:
tell application "TextEdit"
words of text of documents
end tell
Both approaches work exactly the same, so just use whichever one you find easier to
read.
Identifying an Element by Its Index, or Position
The by-index reference form uses a whole number, or integer, to identify an element by
its position. To use the index reference form, you type the element’s class name
followed by the position of the specific element you want:
element_class index_number
For instance, to get the third file of the second folder of the first disk in Finder:
tell application "Finder"
file 3 of folder 2 of disk 1
end tell
Notice that the first element of an object is referred to as item 1. This is known as onebased indexing.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
131
CAUTION: Traditional programmer-oriented languages use zero-based indexing, where the first
item’s index is 0, not 1. Languages such as AppleScript that are designed for ordinary users
generally prefer one-based indexing, however, because that is how humans usually count.
The index reference form uses the order of the elements in the way the application
defines that order. In the Finder, for the most part, the files are arranged alphabetically.
In page-layout applications, the order of page elements is determined based on their
stacking order; the topmost item is always item 1. The order of some objects, such as
pages and paragraphs, is easy to determine.
The index reference form is particularly convenient for referring to the frontmost
document, since document elements are always ordered from front to back. Thus, to
address commands to the front document, just direct them to document 1. The following
script counts the number of words in the front TextEdit document:
tell application "TextEdit"
tell document 1
count every word
end tell
end tell
TIP: If you don’t find this sort of phrasing “English enough” for your tastes, you can even use
keywords—first, second, third, etc.—instead of index numbers 1 to 10, or you can write
any index number like this: 1st, 2nd, 3rd, and so on; for example: first character of
19th word of tenth paragraph of 1st document.
The index reference form works from the back as well by specifying negative numbers.
The last item is also item –1, one before the last item is –2, and so on. For example, to
bring the backmost window in the Finder to the front:
tell application "Finder"
select window -1
end tell
There are four more keywords you can use when identifying a single element by
position: front (which is the same as first), last, middle, and some. As it sounds, these
keywords identify a single element based on its position in the collection of elements.
The meanings of the front/first, last, and middle keywords should be obvious
enough, identifying the first, last, or middle element of an object. The some keyword is
especially neat, because it allows you to pick an element completely at random. Here
are some examples:
tell application "Finder"
close front window
end tell
tell application "TextEdit"
get middle word of last document
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
132
CHAPTER 5: Understanding How Application Scripting Works
end tell
tell application "iTunes"
play some track
end tell
Identifying an Element by Its Name
Many application-defined objects contain a name property, allowing you to identify that
object by name. As a general rule, if the class definition includes or inherits a name
property, then you can refer to objects of that class by name.
Sometimes it is up to you to name an object in the first place; for example, you can
assign unique names to page items in an Adobe Illustrator document, making them easy
to identify in the future. In most cases, the objects are already named and all you have
to do is refer to the object by name in your script.
You can identify an element by name using the following syntax:
element_class named name_text
However, the named keyword is optional, so in practice it is normally written like this:
element_class name_text
For example, to open a folder named “Applications” on a disk named “Macintosh HD”:
tell application "Finder"
open folder "Applications" of disk "Macintosh HD"
end tell
TIP: If you find it easier to read, you can insert the keyword named between the element’s class
name and name. For example, folder "Applications" can also be written as folder
named "Applications".
The following script creates a new AppleScript Editor document named “My Script” and
then refers to that document by name:
tell application "AppleScript Editor"
make new document with properties {name:"My Script", ¬
contents:"tell application \"Finder\" to activate"}
execute document "My Script"
end tell
By-name references tend to be a bit more reliable than by-index references. Let’s say
your script identifies a TextEdit document according to its position, like this:
tell application "TextEdit"
tell document 1
-- Some commands to manipulate the document...
end tell
end tell
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
133
This is fine if the document you want to work in is always the frontmost document in
TextEdit’s GUI. However, if the order of TextEdit’s document elements changes halfway
through—for example, because you minimized the document window or opened another
text file—then the rest of your commands will end up manipulating a different document
from the one you started on.
However, if you can identify an element by its name, it is much easier to keep track of
the element you want (assuming the value of the object’s name property doesn’t change,
of course). The only catch is if an object has two or more elements with identical names.
In this situation, the application will use the first of these elements and ignore the rest.
This isn’t an issue with some applications such as the Finder, where each element of an
object has to have a unique name, but it is something you need to be aware of when
dealing with, say, document elements in TextEdit or AppleScript Editor.
Licensed by
Jim Kilcullen
2884260
Fortunately, there is a third reference form that can reliably locate the same object every
time, even if the object does move around or find itself among identically named
neighbors…
Identifying an Element by Its Unique ID
Although names are useful, some applications provide an additional identifier for some
or all of their objects: a unique ID. When the application creates an object, it assigns a
unique ID to an object’s id property. As a general rule, if the class definition includes or
inherits an id property, then you can refer to objects of that class by ID. The id property
is read-only, which means that it cannot be changed once the object is created. Also, no
two objects within the application can share the same ID.
A by-ID specifier consists of the element class, followed by the keyword id, followed by
the ID value itself.
element_class id id_value
For example, when you ask Safari for its window objects, the result is a list of by-ID
references:
tell application "Safari" to get every window
--> {window id 293 of application "Safari", window id 294 of application "Safari"}
The unique and unchanging nature of object IDs makes them especially useful to your
scripts. Although the index or name of an object might change over time—for example,
when the object is renamed or moved to a different position—its ID is permanent. If your
script needs to store a by-index or by-name reference to an object, and the object’s
position or name changes, the next time you try to use that reference to locate the
object, you could easily end up with a completely different object instead. However, if
you can get a by-ID reference instead, then you can be certain that the next time you
use that reference, it will still be pointing to the same object as before (assuming that
object still exists, of course).
Different applications may use different ID formats. For example, iTunes uses whole
numbers (integers) as object IDs:
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
134
CHAPTER 5: Understanding How Application Scripting Works
tell application "iTunes"
get playlist 1
end tell
--> library playlist id 44 of source id 43 of application "iTunes"
In Address Book, each person object’s ID is a long and cryptic-looking piece of text:
tell application "Address Book"
get id of person 1
end tell
--> "DE1F7D95–2FC6-4F0A-89ED-5ED52C0CE1D9:ABPerson"
Only the application itself knows what a particular ID value means, so when constructing
by-ID references from scratch, you should only use ID values that have come from the
application. Also, some applications may use different ID values the next time they are
launched, so you should be cautious of reusing by-ID references or ID values provided
by the application on a previous run.
Applications that assign unique IDs to most or all of their objects include Address Book,
iCal, iTunes, and Adobe InDesign. Other applications such as Finder, TextEdit, and
Adobe Illustrator don’t use IDs nearly as much (or not at all), so you will have to make do
with whatever by-index and/or by-name references they do provide.
Identifying an Element Before or After Another Element
A relative reference identifies an element that is positioned before or after another
element. The syntax is as follows:
class_name before element_reference
class_name after element_reference
For instance,
tell application "TextEdit"
paragraph before paragraph 3 of document 1
end tell
requires that paragraph 3 of document 1 of application "TextEdit" will be a valid
reference in order for it to be valid itself. If there’s no paragraph 3, then you can’t use the
reference paragraph before paragraph 3 or paragraph after paragraph 3.
The following example selects the photo that follows the currently selected photo:
tell application "iPhoto"
set current_selection to item 1 of (get selection)
select photo after current_selection
end tell
When using relative references, bear in mind that the application will decide what the
previous or next element actually is. For example, if you have selected a photo in one
iPhoto album, when you run the preceding script, the next photo selected might be in a
completely different album.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
135
Identifying a Range of Elements
The range reference form allows you to reference an entire range of elements, instead of
one element at a time. You do this by identifying the first and last elements in the range
you want, using the following syntax:
plural_class_name first_element thru last_element
You can use through instead of thru if you prefer. The following syntaxes also work:
plural_class_name from first_element thru last_element
every class_name from first_element thru last_element
You can specify the first and last elements in several ways. The simplest option is to use
index numbers. The following script will reference a range of records in a FileMaker Pro
database:
tell application "FileMaker Pro"
records 12 thru 16 of database 1
end tell
The next example minimizes all TextEdit windows except the frontmost one:
tell application "TextEdit"
set miniaturized of windows 2 thru -1 to true
end tell
Although this is the most common approach, you can also use strings where that makes
sense. For example, you could refer to a range of people in your Address Book by name:
tell application "Address Book"
people "Rachel Andrews" thru "Sarah Jones"
end tell
A third option is to use short references to the start and end elements themselves. For
example,
tell application "TextEdit"
words 2 thru 4 of text of document 1
end
is really just shorthand for this:
tell application "TextEdit"
words (word 2) thru (word 4) of text of document 1
end
The start and end points are relative references, word 3 and word 6, that will be
expanded using the reference to the container object, text of document 1 of
application "TextEdit", as the base reference. In most applications, this isn’t a
particularly useful way to write references, but some applications allow you to use
different classes of elements for the start and end points. For instance, the following
script obtains several words from a text frame in Adobe Illustrator:
tell application id "com.adobe.illustrator"
contents of words 2 thru 4 of text frame 1 of document 1
end tell
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
136
CHAPTER 5: Understanding How Application Scripting Works
--> {"funny", "thing", "happened"}
That’s fine if all you want are the words themselves, but what if you want all of the text
between the first and last words? In Illustrator, to identify a section of text, you refer to
the text frame’s text elements, like this:
tell application id "com.adobe.illustrator"
contents of text 3 thru 22 of text frame 1 of document 1
end tell
--> "funny thing happened"
However, that assumes you know the exact character positions of the first and last
words. Fortunately, Illustrator allows you to use relative references to the start and end
points in the text range, like this:
tell application id "com.adobe.illustrator"
contents of text (words 2) thru (word 4) of text frame 1 of document 1
end tell
--> "funny thing happened"
Identifying Elements Using the whose Clause
The whose clause, also known as the by-test reference form, is one of the most powerful
features provided by scriptable applications. It gives you the ability to identify elements
whose property and/or element values meet certain criteria. For instance, you might ask
the Finder to identify all files that are larger than 10MB, or perhaps you want iTunes to
locate every track from a particular album that has a 100 percent rating.
Here is the basic syntax:
plural_element_class whose test_expression
You can write where instead of whose if you prefer—both words mean exactly the same
thing to AppleScript. You can also use every class_name instead of the plural class
name if you find it easier to read.
Script 5–10 asks the Finder to identify all files larger than 10MB anywhere in the user’s
Documents folder, while Script 5–11 gets all the names of all the tracks belonging to the
album “Kings of Swing” with a 100 percent rating.
Script 5–10.
tell application "Finder"
every file of entire contents of folder "Documents" of home ¬
whose size > (10 * 1000 * 1000)
end tell
Script 5–11.
tell application "iTunes"
name of every track of library playlist 1 ¬
whose album = "Kings of Swing" and rating = 100
end tell
What makes whose clauses so powerful is that the application itself is responsible for
testing each object. Not only does this save you from having to write the test code
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
137
yourself, the code runs far more quickly. The whole operation is performed in a single
command, with the application doing all of the hard work for you.
Let’s look in more detail at how the test expression in a whose clause is constructed.
Here is the test from Script 5–10:
size > (10 * 1000 * 1000)
As you can see, the first reference contains a property name, size. When the application
evaluates the whose clause, it loops over each of the elements being tested. It then
evaluates any relative references within the test clause—in this case, size—against the
element. So the script asks for the size of file 1, then file 2, and so on. Once the value to
be tested has been retrieved, the test is performed—in this case, checking whether the
size value is greater than 10,000,000 bytes (10MB).
Notice how the original script expressed this number as a multiplication calculation, 10 *
1000 * 1000. This part is actually evaluated by AppleScript before it sends the reference
to the target application. The only operations that scriptable applications know how to
perform are comparison tests, containment tests, and Boolean tests—any other
operations and commands must be performed by AppleScript first. (You’ll learn more
about these operations in later chapters.)
Here is the test clause from Script 5–11:
album = "Kings of Swing" and rating = 100
Here we have two comparison tests being performed—one to check the value of a track
object’s album property, and one to check the value of the track’s rating property. The
results of the two tests are combined by a Boolean operator, and, that returns true only
if both tests pass. If the entire test passes, then the track object is included in the result;
if one or both tests fail, then the object is skipped.
Let’s look at a couple more examples. First, Script 5–12 uses a whose clause to identify
all of the Illustrator text frames that contain no text and delete them.
Script 5–12.
tell application id "com.adobe.illustrator"
delete every text frame of document 1 whose contents = ""
end tell
Script 5–13 shows another example, this time using Address Book.
Script 5–13.
tell application "Address Book"
get name of first person whose (email_address is in (value of every email))
end tell
This example searches for a person with a particular e-mail address. Notice that e-mails
are stored as elements of the person object, so you can’t simply write every person
whose email is email_address. Fortunately, Address Book is pretty clever at
interpreting even fairly complex whose clause tests, so you can ask it to look through
each email element’s value property to see whether the desired address is in any of
them. Had this powerful whose clause not been available, you would have had to use a
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
138
CHAPTER 5: Understanding How Application Scripting Works
pair of nested AppleScript loops to search through each email element of each person
object one at a time—a rather more laborious and far slower solution than getting
Address Book to do all the hard work for you.
Referring to Insertion Locations
All of the previous reference forms have been concerned with identifying objects stored
in properties or as elements of other objects. The insertion reference form is different: it
identifies a point before or after an existing element. Insertion references are normally
used in commands that create, duplicate, or move objects to indicate the place where
the object being created or moved should be inserted.
There are two ways you can specify the insertion location. First, you can pick a position
before the first element or after the last element of an object:
beginning of plural_element_class
end of plural_element_class
This approach works even if no previous elements exist.
Alternatively, if you have a reference to an existing element, you can specify an insertion
point before or after that:
before element_reference
after element_reference
Because insertion references do not identify an application object, you can only use
them in certain commands—typically make, move, and duplicate. For example, TextEdit’s
make command requires an insertion location when adding new paragraphs to a
document, as demonstrated by Script 5–14.
Script 5–14.
tell application "TextEdit"
make new paragraph ¬
at end of paragraphs of text of document 1 ¬
with data "A new paragraph\n"
end tell
NOTE: Some applications require a reference directly to the object into which the new object will
be inserted, rather than an insertion point reference. This is often the case with older applications
such as the Finder and iTunes. Modern Cocoa-based applications normally use insertion location
references, although some parts of the reference may be omitted for convenience; for example,
end of paragraphs of text of document 1 may also be written as end of text of
document 1.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
139
Summary
In this chapter, you learned about the four key concepts behind application scripting:
how applications represent your data as objects, how applications allow you to
manipulate these objects using commands, how these objects are organized into an
object model, and how application dictionaries document all of this information. This is a
lot of material to digest, so let’s spend a bit of time reviewing it.
To begin with, you discovered exactly what makes an object an object. First, you
learned how objects are categorized by class. Two objects of the same class may
contain very different data, but their overall structures are exactly the same. For
instance, the Finder contains many thousands of folder objects, all with different names
and containing different files and subfolders. Because you know that all of these objects
belong to the folder class, you can be certain that they will always have a name property
and file and folder elements, and can be manipulated in the same ways.
You learned how objects can have properties that describe their various characteristics:
name, class, position, color, and so on. Properties can also contain references to other
objects within the application. These are often provided as convenient shortcuts to
objects that are of particular importance to scripters—for instance, the home property of
the Finder or the current track property in iTunes.
You learned how some objects can contain other objects as elements. Although an
object can only ever have one of each property, it can have any number of elements:
one, many, or even none at all. For example, a user playlist in iTunes may contain any
number of file-based tracks, each of which appears as a file track element of the
playlist object.
After exploring the structure of application objects, you next looked at how application
commands are constructed. You learned that every command must have a name, and
many have parameters too. Each parameter is a reference or AppleScript object that will
be passed to the scriptable application as part of the command. Some application
commands have a single direct parameter that appears directly after the command
name, some have one or more labeled parameters where each value is identified by a
keyword-based label, and some commands have both.
Once you learned how to write commands, you learned how commands must be sent to
a target object in order to do their jobs. In the case of application commands, the target
is an object of class application that represents the scriptable application you wish to
manipulate. You also saw how to use AppleScript’s tell statement to specify an
application object as the default target for all commands within the tell block.
Lastly, you learned how application commands may return values as results—these
values may be new application object references or AppleScript values (or a mixture of
both). Or, if the application is unable to perform the desired command, it will report an
error instead.
With the basic building blocks of application scripting now under your belt, you
discovered how applications organize their scriptable objects into object models,
allowing these objects to be explored and manipulated from other applications. You saw
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
140
CHAPTER 5: Understanding How Application Scripting Works
how application objects can be contained within other application objects, usually as
elements, though sometimes in properties too. You also spent some time looking at how
to refer to objects using references. Each reference acts as a set of directions, telling the
application how to navigate through the object model to the object (or, in some cases,
multiple objects) that you wish to work with. You then got some practice exploring a
typical object model (the Finder’s) and constructing references to its objects.
Having explored the mechanics of application scripting, you then learned how to read
the core documentation that comes with every scriptable application: the dictionary. You
learned how to translate the information provided by the dictionary—class and
command definitions—into a practical understanding of the types of objects a scriptable
application provides, how these objects may fit together to form the object model (the
containment hierarchy), and how to write commands to manipulate these objects.
You also learned about inheritance, which is the system by which several classes may
share common features defined by another class. For instance, the item class in the
Finder is inherited by the container and file classes, which in turn are inherited by the
disk and folder classes, and the alias file, application file, document file, and
other file-related classes.
Although you will never meet an object of class item, container, or file in the Finder’s
object model, you will meet plenty of objects of class disk, folder, alias file,
application file, and so on. Knowing how these classes are related to one another
tells you what features objects of these classes have in common—for instance, they all
contain name properties, since this is defined by the item class, while disks and folders
all have folder and file elements of various sorts, as these are defined by the
container class. You also discovered that a good understanding of the application’s
class inheritance hierarchy gives you greater control over the class or classes of objects
you can identify when referring to an object’s elements. For instance, asking for all of the
item elements of a folder gives you its subfolders and all of its files; asking for the file
elements gives you all of its files but not its folder; and asking for its document files
gives you its document file objects only.
Having now covered the four key concepts of application scripting, you spent a bit of
time exploring the application class, learning about the various ways in which you can
identify target applications: by name, by file path, by bundle ID, and by eppc:// URL
(although we will leave the details of the last one until Chapter 12). You also found out
about the useful properties that all application objects provide by default, allowing you
to get information such as the application’s name, version, and running status without
even having to send any commands.
Finally, you spent some time filling in the remaining knowledge needed to construct
references to application objects. Referring to properties is very simple; just give the
property’s name. Referring to elements requires a bit more work: in addition to indicating
the class of element you want, you also have to specify exactly which element (or
elements) you are interested in, based on their position, name, unique ID, or whether
they fall within a given range or meet a particular set of requirements—or you even can
just specify all of them.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 5: Understanding How Application Scripting Works
141
Because AppleScript’s application scripting features are so deeply integrated into the
language itself, it can sometimes be a little difficult to see where the language features
end and the features provided by scriptable applications begin. Still, this chapter should
provide you with some appreciation of how scriptable applications work, while the rest
of the chapters in Part 2 of the book educate you on every aspect of the AppleScript
language itself.
Although the real hands-on application scripting material does not begin until Part 3 of
the book (Chapters 20 to 30), you will get some practical experience of application
automation along the way, as sample scripts and projects demonstrate how AppleScript
features can be combined with scriptable applications to perform all sorts of powerful,
interesting, and fun tasks. Just remember: any time you encounter a piece of code that
involves application scripting, you can come back to this chapter to check up on any
details you are unsure of.
In the next chapter, we begin our exploration of the first of our AppleScript key
concepts: how the AppleScript language represents information as objects of its own.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
142
CHAPTER 5: Understanding How Application Scripting Works
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
143
Chapter
6
Learning to Work with
AppleScript Objects
Licensed by
Jim Kilcullen
2884260
Now that we’ve discussed the principles of application scripting in detail, let’s turn our
attention to the AppleScript language itself.
Chapter 2 introduced you to the four key concepts that underlie AppleScript (and other
scripting languages):
How AppleScript represents information as objects
How AppleScript manipulates objects using commands, operators,
and variables
How AppleScript makes decisions on what to do and when to do it
How AppleScript organizes code using handlers and script objects
I will cover the last two concepts—making decisions and organizing your code—later in
the book, in Chapters 14, 15, 18, and 19. For now, I want to spend some time exploring
the first two concepts.
Although AppleScript is a fairly small language, it will still take us some time to cover all
the important aspects of representing and manipulating data. To simplify the process, I
have broken down this coverage into a number of chapters.
The first two sections in this chapter map out the two key concepts in a bit more detail,
describing how data is represented by AppleScript objects and introducing the features
that you can use to manipulate these objects. The final section in this chapter introduces
you to the first of several AppleScript classes: the boolean class.
Chapters 7 to 10 will describe some of the more powerful objects you will meet in
AppleScript: numbers, strings, dates, lists, and records. Chapters 11 and 12 will fill in
the remaining details on working with variables and commands, and Chapter 13 will
complete your understanding of operators and coercions.
Let’s get started.
143
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
144
CHAPTER 6: Learning to Work with AppleScript Objects
How AppleScript Represents Information As Objects
As previous chapters have mentioned, both AppleScript and scriptable applications
represent individual pieces of information as objects. Application objects are fairly
complicated structures that represent application-specific data—documents, playlist
tracks, calendar events, and so on—and are found only in scriptable applications.
AppleScript objects are much simpler structures that represent the most basic pieces of
information that your scripts can work with: numbers, plain text, dates, and so forth.
Unlike application-defined objects, AppleScript objects can live within the AppleScript
language itself and can easily be passed from one application to another.
Now let’s take a look at how AppleScript objects are structured and how they behave.
Although objects in AppleScript are not the same as the objects you find in application
object models, they are not that different, either. You can create new objects, you can
get information about objects, you can manipulate objects using commands and other
features, and some objects can even be used to hold other objects.
What Kinds of Objects Does AppleScript Provide?
In Chapter 5 you saw how application dictionaries categorize different kinds of
application objects according to their class: document, window, disk, track, and so forth.
The AppleScript language categorizes its own objects in exactly the same way,
describing each object as belonging to a particular class.
Here are the main classes of objects you will find in AppleScript:
class
constant
boolean
integer
real
text
date
alias
file
POSIX file
list
record
data
script object
application
reference
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 6: Learning to Work with AppleScript Objects
145
Some of these class names should be self-explanatory: for example, an object of class
integer represents a whole number (integer); an object of class text represents a piece
of plain text; an object of class list is an ordered collection of other objects. Other
classes such as boolean, alias, and script object aren’t as obvious, but don’t worry:
they will all be explained in this and later chapters.
Creating New Objects
Creating new objects is especially easy in AppleScript. Creating a new application
object requires the use of an application command such as make, but you can create a
new object just by typing its literal representation in your script and running it.
For example, type 89 in your script, and when AppleScript executes that code it will
create a new integer object representing the number 89. Run the code "Hello World!",
and AppleScript will create a new text object containing the phrase “Hello World!”
AppleScript provides special syntax to represent several basic classes of object in your
code; for example, a pair of double quote marks indicates where a text object, or string,
begins and ends:
"Hello World!"
Other types of object, such as dates, do not have their own special syntax but instead
use AppleScript’s standard object-specifier syntax, consisting of the class name
followed by a string containing the raw data to be used in creating that object:
date "Wednesday, July 1, 2009 3:45:20 PM"
TIP: A newly created AppleScript object remains in existence only for as long as it is in use. If
you want to keep hold of an object so that you can use it again later in your script, you can do
this by storing it in a variable. More details on variables are provided later in the chapter.
Getting Information from Objects
In Chapter 5, you learned that an application-defined object normally possesses one or
more properties containing information about that object. For example, every object has
a class property that tells you what kind of object it is:
class of 89
--> integer
class of "Hello World!"
--> text
Some objects may have additional, built-in properties; for example, text, list, and record
objects also have length properties that tell you how long they are:
length of "Hello World!"
--> 12
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
146
CHAPTER 6: Learning to Work with AppleScript Objects
length of {"Hello", " ", "World", "!"}
--> 4
Some classes of AppleScript objects even allow you to define your own properties. For
example, here is a record object containing two properties, name and age:
{name:"John Smith", age:900}
Some objects also have elements. For example, to extract a word from a larger string,
just refer to the word element you want:
word 2 of "Hello World!"
--> "World"
In addition to working with their properties and elements, you can also manipulate
objects using various AppleScript features. We’ll look at these features next.
How AppleScript Works with Objects
When working with objects in scriptable applications, there is one way to manipulate
them: by sending commands to the application. AppleScript objects can also be
manipulated with commands, but this is not the only way: AppleScript provides two
other important features for manipulating objects: operators and coercions. In addition,
it provides a fourth feature, variables, that allows you to store objects within your script
so that you can use them again later.
Let’s look at each of these in turn.
Manipulating Objects with Commands
For a language that spends so much time sending commands to other applications,
AppleScript has surprisingly few commands built into it: just five, in fact.
Fortunately, there are a couple of ways to provide AppleScript with access to additional
commands: by installing special application plug-ins, called scripting additions, and by
defining your own commands in your scripts.
Introducing the Five Built-in Commands
The AppleScript language defines just five commands itself: get, set, copy, count, and run.
The first two commands, get and set, are used to retrieve and assign objects that are
stored within variables, or as properties or elements of other objects. For example:
set the_variable to "Hello World!"
get the_variable
--> "Hello World!"
If the get and set commands sound familiar, that’s because AppleScript also uses these
two commands to get and set properties and elements within application objects. As
with application scripting, you hardly ever need to write explicit get commands in your
script, because AppleScript will automatically retrieve a value for you when you refer to
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 6: Learning to Work with AppleScript Objects
147
the property, element, or variable where it is stored. So, for example, although you can
retrieve a value like this,
get length of "Hello World!"
--> 12
it is normal to omit the get part and just write this:
length of "Hello World!"
--> 12
The copy command works a lot like the set command in that it assigns values to
properties, elements, and variables. There is one big difference, however: whereas the
set command assigns the value you give it, the copy command makes an exact copy of
the original value and assigns that instead.
NOTE: The difference between set and copy becomes very important when working with
objects such as lists and records whose contents can be modified by AppleScript. We’ll discuss
this issue in detail in Chapter 12.
The fourth built-in command, count, can be used to count the number of characters in a
string, the number of elements in a list, or the number of properties in a record.
The final command, run, can be used to do what its name suggests: run a script.
Later chapters will explore all five built-in commands in greater detail, so for now let’s
move on and look at the ways in which extra commands can be added to supplement
AppleScript’s own.
Introducing Scripting Addition Commands
Scripting additions are plug-ins that provide additional commands for AppleScript to
use. Mac OS X ships with one important scripting addition, Standard Additions, already
included, and there are plenty of third-party scripting additions available that you can
install yourself.
The Standard Additions scripting addition, for example, provides AppleScript with a
range of commands for displaying simple dialog boxes and reading and writing files,
among other things. In fact, the very first script you wrote in this book used one of the
Standard Additions commands, display dialog, to show a “Hello World!” message
onscreen:
display dialog "Hello World!"
Third-party scripting additions may add commands for other tasks, such as changing a
string to all-uppercase or all-lowercase text, performing trigonometric math calculations,
working with XML data, and so on.
The next few chapters will describe several Standard Additions commands that are of
particular use when working with numbers, strings, and dates. Later chapters will
explore other areas in which scripting addition commands are used, and Chapter 22 will
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
148
CHAPTER 6: Learning to Work with AppleScript Objects
cover all the technical aspects of using scripting additions, including where and how to
install your own. For now, however, you don’t need to worry about the technical details,
so just use the Standard Additions commands as if they were a part of the language
itself.
Introducing User-Defined Commands
One of the more advanced, but very cool, features of AppleScript is that it allows you to
define your own commands using the language itself. This feature becomes increasingly
useful as your scripts grow larger and more complex, as it allows you to organize
chunks of AppleScript code into neat little packages, called handlers, that your script
can then run by sending itself some commands.
For example, you might define one handler to find and replace a particular piece of text
within a larger string, and another handler to take a list and sort its items into ascending
order. In Chapter 2, I showed a very simple example of a command handler called
square_root that takes a number, calculates its square root, and returns it:
square_root(25)
--> 5.0
on square_root(the_number)
return the_number ^ 0.5
end square_root
Writing your own handlers from scratch is a topic best left for later on in the book—
Chapter 18, to be exact—but this shouldn’t stop you from copying and using some of
the prewritten handlers provided in the following chapters. Although user-defined
commands normally use a syntax that is slightly different from AppleScript- and
scripting addition-defined commands, their goal is the same: to manipulate data.
So far in this chapter, I’ve talked about objects and commands in AppleScript. Although
some technical differences may exist between these objects and commands and the
objects and commands you find in scriptable applications, the basic concepts are not
too different. Now, however, it’s time to introduce a brand new feature to you, one that
you won’t find in scriptable applications: the operator.
Manipulating Objects with Operators
What are operators? Well, you might be a little disappointed to hear this, but they are
not really all that different from commands, as the goal of both operators and
commands is to manipulate data. (Some languages don’t even bother with operators at
all, and just use regular commands to provide all their functionality.)
All AppleScript operators take either a single object (unary operators) or a pair of objects
(binary operators), perform some sort of calculation, comparison, or other
transformation, and return a new object as a result. In grammar terms, we refer to the
objects that are passed to an operator as operands, and to the combination of operator
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 6: Learning to Work with AppleScript Objects
149
and operand(s) as an operation. For example, in the following math operation, the
addition operator, +, has two operands, 2 and 5, that appear on either side:
2 + 5
When this operation is executed, the addition operator calculates the sum of the two
numbers and returns a new value, 7, as the result.
What Makes Operators Special?
Although it is tempting to think of an operator as just a special kind of command, it is
important to know what the differences are.
The first unique feature of operators is that they can be provided only by the AppleScript
language itself. In addition, the number of operators that AppleScript provides is
completely fixed: there are 26 in total.
The second characteristic of operators is that they are expressions. This means that they
will always return an object. Most commands also return an object, but some do not—
unlike operators, it’s up to the command’s designer to decide whether or not the
command should return a result.
The third feature is that each operator has its own special syntax provided by the
language itself. For example, the concatenation operator, which previous chapters have
already mentioned, is written as an ampersand, &, symbol, with the two objects that are
being joined appearing on either side:
"Hello " & "World!"
The final distinguishing feature of operators is that AppleScript has its own special set of
rules that it follows when evaluating two or more nested operator expressions. You will
need to learn these rules in order to combine operators effectively; fortunately, most of
the rules that govern evaluation order are pretty intuitive, as they are designed to be
consistent with the rules of math you learned in school. For example, the rules for
evaluating an expression containing several math operators are the same as the rules
used in regular math: multiplication and division operations are performed before
addition and subtraction, while calculations within parentheses are carried out before
the calculations outside of them. Here are a couple of examples to illustrate:
2 + 3 / 5
--> 2.6
(2 + 3) / 5
--> 1
In the first example, the division operation takes precedence over the addition operation,
so it is calculated first: 3 divided by 5 returns 0.6, and this is added to 2 to produce the
final result, 2.6. In the second example, the parentheses have even higher priority than
division, so 2 and 3 are added first to give 5, which is then divided by 5 to produce 1.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
150
CHAPTER 6: Learning to Work with AppleScript Objects
Don’t worry too much about operator precedence for now: the next few chapters will fill
in any details as they’re needed, and Chapter 13 will provide a full summary of
AppleScript’s precedence rules, for your future reference.
Let’s now take a quick look at the different kinds of operators that AppleScript provides.
What Kinds of Operators Does AppleScript Provide?
AppleScript’s 26 operators can be broken down into several different groups according
to what they do. The following sections provide a brief summary of each of these groups
to get you started; subsequent chapters will explain in detail the operators that are
relevant to the objects being discussed.
The Concatenation Operator
Probably the most used operator in AppleScript is the concatenation operator, &.
To concatenate means to join together. For example, AppleScript’s concatenation
operator can concatenate two strings to create a new string, two lists to produce a third
list, and two records to create a third record:
"Hello " & "World!"
--> "Hello World!"
{1, 2, 3} & {3, 2, 1}
--> {1, 2, 3, 3, 2, 1}
{name:"John Smith"} & {age:900}
--> {name:"John Smith", age:900}
Chapters 7 and 10 will look at this very useful operator in more detail.
Math Operators
Next are the math operators, which are used to work with numbers (integer and real
values). Table 6–1 lists the available math operators and their names, and provides a
brief summary of what they do.
Table 6–1. Math Operators
Operator
Name
Description
+
Addition
Adds the left and right numbers.
-
Negation
(with one operand)
Converts the single number to its right from positive to
negative or from negative to positive.
-
Subtraction
(with two operands)
Subtracts the right number from the left number.
*
Multiplication
Multiplies the left and right numbers.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 6: Learning to Work with AppleScript Objects
Operator
Name
Description
/
Division
Divides the left number by the right number.
div
Integral division
Returns the number of times the right number fits whole in
the left number.
mod
Remainder (modulo)
Subtracts the right number from the left number repeatedly
until the remainder is less than the right number and returns
the final remainder.
^
Exponent
Raises the left number to the power of the right number.
151
Chapter 8 will explain in a lot more detail how you can use these math operators.
Comparison Operators
Comparison operators basically ask a simple question: is the left operand less than,
greater than, or the same as the right one? The result of a comparison can be either
true or false. Table 6–2 summarizes the six comparison operators available.
Table 6–2. Comparison Operators
Operator
Name
Description
=
Is equal to
Returns true if both operands are the same.
≠
Is not equal to
Returns true if the operands are different.
<
Is less than
Returns true if the left operand is less than the right operand.
≤
Is less than
or equal to
Returns true if the left operand is less than or equal to the right
operand.
>
Is greater than
Returns true if the left operand is greater than the right operand.
≥
Is greater than
or equal to
Returns true if the left operand is greater than or equal to the right
operand.
I will discuss throughout the next four chapters where and how you can use these
operators.
Containment Operators
Containment operators check whether one object can be found inside another, returning
true or false as a result. AppleScript provides six containment operators—these are
listed and described in Table 6–3.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
152
CHAPTER 6: Learning to Work with AppleScript Objects
Table 6–3. Containment Operators
Operator
Description
starts with
Returns true if the second operand appears at the start of the first.
ends with
Returns true if the second operand appears at the end of the first.
contains
Returns true if the second operand appears anywhere within the first.
does not contain
Returns true if the second operand does not appear in the first.
is in
Returns true if the first operand appears anywhere within the second.
is not in
Returns true if the first operand does not appear in the second.
All of these operators can be used on strings and lists, and some can be used on
records as well. We’ll look at using containment operators in Chapters 7 and 10.
Boolean Operators
AppleScript has three Boolean operators—and, or, and not—that are used when
working with Boolean values. I’ll discuss these operators in the “Working with Boolean
Objects” section later in the chapter.
The Coercion Operator
Coercion is the process of converting an object of one class to a comparable object of
another class. For instance, the value 5 is an integer, and the value "5" is a string. You
can’t do math with "5", and you can’t concatenate 5 to another string as long as it is an
integer. So, to do math with the string value "5", you must convert it, or coerce it, into a
number. Similarly, to use the number value 5 in a string, you must coerce it into a string.
To perform coercion operations, you use the coercion operator, as. This takes two
operands: the left operand is the object to be coerced, and the right operand is the
name of the class you want to convert it to. For example:
5 as text
--> "5"
NOTE: AppleScript also has the ability to coerce objects automatically in certain situations. We
refer to this process as implicit coercion, to distinguish it from explicit coercions performed using
the as operator.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 6: Learning to Work with AppleScript Objects
153
The a reference to Operator
The last operator in AppleScript is a reference to. This is a more advanced feature that
you won’t need to use very often, so I won’t say anything more about it here. Chapter 13
will explain what this operator does, after you’ve finished learning about the different
types of objects it can be used with.
Coercing Objects
As I mentioned when discussing AppleScript’s coercion operator (as), coercion is the
process of converting an object of one class into an equivalent object of another class.
In fact, there are two ways in which coercions can happen.
Licensed by
Jim Kilcullen
2884260
The first way in which a coercion occurs, as previously described, is when your script
uses the as operator to instruct AppleScript to perform the conversion—what we call an
explicit coercion. In the following example, the current date command returns an object
of class date that represents the current date and time:
current date
--> date "Wednesday, July 1, 2009 3:45:20 PM"
If we want to get the date and time as a string object instead, we can easily convert the
original date object by coercing it to an object of class text:
(current date) as text
--> "Wednesday, July 1, 2009 3:45:20 PM"
The second way in which a coercion occurs is when you pass an object to a command
or operator that requires a different class of object from the one you gave it. In this
situation, the command or operator will often try to coerce the supplied object to the
required class by itself—what’s known as an implicit coercion.
For example, AppleScript’s math operators all require either whole numbers (integers) or
decimal numbers (reals) as operands:
3 + 5
--> 8
However, you can also use other classes of objects as operands, just as long as those
objects are capable of being coerced to numbers. For example, if you pass two strings,
AppleScript will automatically attempt to coerce them to numbers before performing the
addition:
"3" + "5"
--> 8
Of course, this will only work as long as each string contains only numerical characters;
if you try to pass strings that don’t make sense as numbers, you will get a coercion error
instead:
"Hello" + "World"
-- AppleScript error: Can’t make "Hello" into type number.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
154
CHAPTER 6: Learning to Work with AppleScript Objects
You will discover which coercions can be applied to each class of AppleScript objects in
this and subsequent chapters. Chapter 13 provides a convenient cross-reference to all
the operators and coercions found in AppleScript
Storing Objects in Variables
Variables are the “memory” of AppleScript. Unlike commands and operators, variables
are not used to manipulate objects. Instead, their job is to store objects while you aren’t
using them. Any time you have an object that you will need again later in your script, you
can assign that object to a variable. Whenever you need to use that object again, you
can retrieve it simply by referring to the variable you stored it in.
Every variable has a user-defined name, or identifier, that you give it when you first
assign an object to it. It is this name that you use when you want to refer to the variable
again later on.
To assign a value to a variable, you use AppleScript’s set command. Let’s try an
example. Open a new AppleScript Editor window, and type the following:
set the_city to "Providence"
This statement assigns a string, “Providence”, to a variable named the_city.
AppleScript recognizes the_city as a user-defined identifier because it is a single piece
of unquoted text that is not a known keyword. Because the word “Providence” is in
quotes, AppleScript knows it’s literal text, not an identifier.
When you run this code, the variable the_city will have the string “Providence”
assigned to it. To retrieve the string object, just refer to the_city again:
the_city
--> "Providence"
Let’s take this example a little further. First, type another statement to assign a second
object to a variable named the_state:
set the_state to "Rhode Island"
Now you can do something with these variables. Type the following line:
set my_greeting to "Hello, I live in " & the_city & ", " & the_state
Here we retrieve the strings stored earlier in our two variables, the_city and the_state,
and use three concatenation operators (&) to join these and other strings together to
form a new string. Lastly, we assign this new string to a third variable, my_greeting.
To finish this example, we can use a command, display dialog, to display the
completed greeting in a dialog box:
display dialog my_greeting
Figure 6–1 shows the completed script, and the dialog box that is displayed when the
script is run.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 6: Learning to Work with AppleScript Objects
155
Figure 6–1. The completed script, using variables, concatenation operators, and a display dialog command
to display a text message
How Are Identifiers Written?
When naming a variable, you must follow several rules in order for your code to compile
correctly. The rules for writing a valid identifier will be covered fully in Chapter 11, but for
now here are the main ones you need to know:
It must start with an alphabetic character (a–z, A–Z) or underscore (_).
It can contain any number of additional alphabetic characters, digits
(0–9), and underscores.
It cannot be the same as a keyword defined by a scriptable application
(this only applies within an application tell block), an installed
scripting addition, or AppleScript itself.
NOTE: Identifiers are case insensitive; however, once you use a variable in a script, AppleScript
will remember how you typed it, and anywhere else that you use it, AppleScript will change the
case of the characters in the variable to match the same pattern you used the first time.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
156
CHAPTER 6: Learning to Work with AppleScript Objects
Where Can Variables Be Used?
When you define a variable in one part of your script, other parts of your script may or
may not be able to see that variable. For example, a variable that is defined inside a
handler normally can be accessed only by the code within that handler—the rest of your
script cannot see it. This area of visibility is referred to as the variable’s scope.
WHAT’S THE POINT OF VARIABLE SCOPES?
As a new scripter, you may find variable scopes frustrating to deal with: you create a variable in one
section of your script and later try to use it in another…only to have AppleScript insist that the variable
doesn’t exist! You might think AppleScript is just being obstructive…and it is, but for a very good reason.
As you will learn in later chapters, restricting the visibility of a variable within your script can be an
incredibly powerful technique for keeping your code manageable.
For example, suppose you have a 1000-line script, and every one of those lines appears in the same
scope. This means that each variable in your script could be manipulated by up to a 1000 different lines of
code! Whereas, if the same code is divided across 50 different handlers, you only have to look at 20 lines
of code when figuring out what happens to a variable whose scope is limited to one of those handlers.
For now, I just want you to get a rough idea of how and where variables can be defined
and used. For example, if you define a variable in one scope, you can refer to that
variable from anywhere in the same scope. On the other hand, if you write its name in a
second, unrelated scope, what you actually have is two completely separate variables
which happen to use the same name.
Imagine you work in the accounts department under a boss named George. As long as
you work in that department, whenever you mention “the boss,” everyone knows you
are referring to George. If you move temporarily to the marketing department, which has
a different boss, Sue, now when you talk about “the boss,” everyone knows you are
referring to Sue. When you return to your original department, “the boss” will once again
refer to George. And if you leave employment altogether, referring to “the boss” will no
longer have any meaning at all.
Let’s express this glittering career path in AppleScript:
work_in_accounts()
display dialog "Now I've retired, my boss is " & the_boss
on work_in_accounts()
set the_boss to "George"
display dialog "Working in accounts for " & the_boss
work_in_marketing()
display dialog "Back working in accounts for " & the_boss
end work_in_accounts
on work_in_marketing()
set the_boss to "Sue"
display dialog "Now working in marketing for " & the_boss
end work_in_marketing
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 6: Learning to Work with AppleScript Objects
157
So, what happens when this script runs?
Well, AppleScript starts by running any statements at the top level of the script—in this
case, the two lines at the top of the script. The first line sends a work_in_accounts
command to the script, causing it to execute the statements in the work_in_accounts
handler. Here we create a variable named the_boss and assign it an object, "George".
We can then refer to the_boss to retrieve that object and use it, in this case to display
the message “Working in accounts for George”.
Next we send a work_in_marketing command, causing AppleScript to run the
statements in the work_in_marketing handler. Here we create a new variable. This
variable is also named the_boss, but because it is in a separate handler, it is not related
to the the_boss variable in the work_in_accounts handler.
How can we tell that these variables are unrelated, even though they have the same
name?
Well, once the work_in_marketing handler displays its own dialog message, “Now
working in marketing for Sue”, it runs out of statements to execute, so AppleScript
returns to the work_in_accounts handler at the same point it left it. And the next
message displayed is… “Back working in accounts for George”. As you can see, the
value of the_boss in the work_in_accounts handler was not affected by the set the_boss
to "Sue" statement in the work_in_marketing handler, because the variables that are
visible in one handler are not visible inside the other, and vice versa. We call these
variables local, because their scope is limited to a single handler.
Finally, the script finishes running the work_in_accounts handler, and returns to
executing the top-level statements. However, when it tries to run the final top-level
statement, rather than displaying a “Now I’ve retired, my boss is…” message, an error
occurs instead: “The variable the_boss is not defined.”
Of course, handlers wouldn’t be very useful if there wasn’t some way to pass values
from one to another, so AppleScript provides ways to do that. You can even make
variables visible throughout the entire script, by defining them as properties or globals.
For now, you’re not moving about departments, so you have nothing to worry about. As
long as a script doesn’t contain any user-defined handlers, you can be sure that using a
certain variable name always refers to the same variable. Later chapters will discuss in
great detail the implications of using variables in handlers, global and local variables,
and properties.
Now that you know a bit more about AppleScript objects in general, it’s time to examine
some of the more important AppleScript classes in detail, beginning with the boolean
class.
Working with Boolean Objects
The boolean class (named after the inventor of Boolean logic, George Boole) is one of
the simplest classes you will meet in AppleScript. There are only two objects of this
class: true and false. Despite its simplicity, however, it is still a very important class,
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
158
CHAPTER 6: Learning to Work with AppleScript Objects
and Boolean objects are used throughout AppleScript, particularly in the area of
decision-making, where many questions ultimately resolve to simple “yes” or “no”—true
or false—answers.
AppleScript provides three Boolean logic operators specially for working with Boolean
objects: and, or, and not. In Boolean operations, both operands and the result are
Booleans. Several other AppleScript operators—in particular, the comparison and
containment operators—also return Boolean values as their results. Boolean operators
are often used in complex expressions to combine the results of two or more
containment and/or comparison operations.
AppleScript does not provide any commands specifically for working with Boolean
values. However, many commands also use Boolean values as parameters or as return
values—for example, the Finder’s exists command returns true or false depending on
whether or not the object you’re referring to can be found.
Boolean Operators
The meaning of the operators and, or, and not is pretty self-explanatory, much like the
use of these words in the English language. For example, in a Boolean and operation, if
the left operand is true and the right operand is true, the resulting value will be true
too.
Using and, or, and not correctly in AppleScript does require a little care, however.
Although it’s okay to say something like “If the score is 9 or 10, then say ‘Excellent!’” in
English, if you try that in AppleScript, you’ll get an error when you run it because 10 is
not a Boolean value. You have to phrase the test expression in strictly logical terms:
the_score is 9 or the_score is 10.
Let’s look at each of these operators in turn, beginning with the simplest one, not.
The not Operator
The not operator takes a Boolean value as its sole, right-side operand and returns the
opposite Boolean value. If the operand is true, the result is false. If the operand is
false, the result is true.
The following script snippets show the not operator in action:
not true
--> false
not false
--> true
not (1 + 2 = 3)
--> false
Because the expression (1 + 2 = 3) results in the Boolean value of true, putting the
not operator before it reverses the result to false.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 6: Learning to Work with AppleScript Objects
159
The not operator is useful in various situations. One is reversing a Boolean value when
testing its value in a conditional statement. Here’s a practical example that creates a
folder named “TO DO” on your desktop if it doesn’t already exist:
tell application "Finder"
if not (folder "TO DO" of desktop exists) then
make new folder at desktop with properties {name:"TO DO"}
end if
end tell
The and Operator
The and operator takes two Boolean operands and returns true only if both operands
are true. If either operand is false, it returns false. Here are some examples of the and
operator in action:
true and true
--> true
true and false
--> false
false and true
--> false
false and false
--> false
And here are some practical examples of using and:
if (email_address contains "@") and (email_address contains ".") then
-- Create and send an email here...
else
-- Display an "invalid email address" error dialog here...
end if
Or, if you just want a variable whose value is true or false, use something like this:
set is_valid_address to (email_address contains "@") and (email_address contains ".")
Notice the use of the parentheses. They are not required in this case, but they visually
distinguish the different operations, making the code easier to read.
To check if a variable, x, is within a range of numbers, say between 10 and 20 inclusive,
you can use the following statement:
if (x ≥ 10) and (x ≤ 20) then
-- Do something here...
end if
The or Operator
The or operator takes two Boolean operands and returns true if either operand is true.
If both operands are false, it returns false. Here are a few examples:
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
160
CHAPTER 6: Learning to Work with AppleScript Objects
true or true
--> true
true or false --> true
false or true --> true
false or false --> false
if (email_address ends with ".net") or ¬
(email_address ends with ".com") or
(email_address ends with ".org") then
-- Do something here...
end if
How Boolean Operators Are Evaluated
One important feature when using the and operator is that if the value of the left operand,
which is evaluated first, is false, the right operand will never get evaluated. This is useful
in situations where you have two test expressions joined by an and operator, and
attempting to evaluate the second test when the first one had already returned false
would cause an error.
To demonstrate, consider the following example:
tell application "TextEdit"
if (document 1 exists) and (text of document 1 is not "") then
-- Process the document's text here...
end if
end tell
Look at the and operator in the second line. The command on its left side checks
whether document 1 exists, while the expression on its right checks whether document
1 has any text. If AppleScript saw that the document didn’t exist but went on to ask for
its text anyway, this would cause TextEdit to raise a “Can’t get document 1” error.
Fortunately, AppleScript is smarter than this and knows that if the first operand is false,
the and operation’s eventual result must always be false as well. This means
AppleScript knows there’s no point in getting the second operand, and therefore no
need to evaluate the second expression, so it doesn’t get it. If the document does not
exist, the entire and operation immediately returns false, and AppleScript moves
straight to the next statement without any trouble.
The or operator is “short-circuited” in a similar fashion; however, in its case, the right
operand is ignored when the left one is already true.
Boolean-Related Coercions
AppleScript allows you to coerce Boolean values to several other classes of objects:
integer, text, and list.
When coercing true and false objects to integers, the result is always 1 or 0:
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 6: Learning to Work with AppleScript Objects
161
true as integer
--> 1
false as integer
--> 0
If you coerce true and false to strings, the result is either "true" or "false":
true as text
--> "true"
false as text
--> "true"
You can also coerce Boolean values to lists, where each list contains the original object,
true or false:
true as list
--> {true}
false as list
--> {false}
The reverse coercions also work: 1, "true", and {true} can all be coerced to true, and
0, "false", and {false} will all coerce to false.
There is one more coercion that you can perform with Boolean values: you can coerce
them to boolean too:
true as boolean
--> true
false as boolean
--> false
In fact, all objects in AppleScript can be coerced to their own class. This might not
sound very useful in itself, but it can come in handy in some situations where you are not
quite sure what class of object a command or other piece of code may give you. To be
sure that you get the class of object that you need (or an obvious error message if the
value is completely unsuitable), just add an explicit coercion. We’ll look at this technique
in later chapters, once we’ve covered the other AppleScript features you will need.
Summary
In this chapter, you learned more about AppleScript objects in general: what they are,
what kinds (classes) of objects are available, how they can be manipulated using
commands, operators, and coercions, and how they can be stored in variables.
This chapter also introduced you to the first of several important and commonly used
objects in AppleScript: the two Boolean values, true and false. You learned what these
objects are used for, and what operators and coercions could be used to manipulate
them.
In the next chapter, we will look at what is perhaps the single most important class in
AppleScript: text.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
162
CHAPTER 6: Learning to Work with AppleScript Objects
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
163
Chapter
7
Working with Text
Licensed by
Jim Kilcullen
2884260
One of the tasks you will find yourself doing a lot in AppleScript is working with text in
one way or another. This chapter covers the many aspects of text manipulation in
AppleScript.
We will begin with a bit of background on how computers make sense of humanreadable text. Next, we will study the various properties and elements of AppleScript’s
text objects, along with the standard operators and commands you can use to
manipulate those objects. We will also spend some time exploring AppleScript’s text
item delimiters—a key feature when breaking text apart or joining it together.
Once you understand the principles behind working with text in AppleScript, we will
round off the chapter with a couple of projects that put this knowledge to practical use.
Introducing Text
Text is found everywhere in Mac OS X: the content of TextEdit and Word documents, as
file and folder names in the Finder, track titles in iTunes, e-mail addresses in Mail…the
list is endless. Given the huge importance of text in Mac applications, it will come as no
surprise that AppleScript provides its own built-in support for representing and
manipulating text within the language itself.
When talking about text objects in the AppleScript language, we normally refer to them
as strings, which is the traditional programmer term for them (as in, “a string of
characters”). I find that talking about “strings” sounds less silly than talking about “texts”
and also helps to distinguish AppleScript’s built-in text objects from the similarly named
but unrelated text objects that belong to scriptable applications such as TextEdit,
Safari, and Mail.
In source code, you indicate a string literal as any number of characters between two
straight double quotes—for example, "Hello World!". Simply having Hello World in the
script without quotes would cause the script to not compile.
163
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
164
CHAPTER 7: Working with Text
As with any other object, you can assign a string to a variable using AppleScript’s set
command:
set my_greeting to "Hello World!"
This line assigns "Hello World!" to the variable my_greeting.
You can do many other things with AppleScript strings, of course, but before we get into
that topic, I’ll take you on a quick trip through time to give you a better understanding of
how representing text on computers works today.
A Brief History of Text
In 1440, Johannes Gutenberg invented the first mechanical printing press. Five hundred
years later, the first digital electronic computers were built. This was a big step
backward for text representation, but fortunately they’ve caught up a lot since then.
When Is Text Not Text?
When it comes to text, computers have a big problem: they only understand numbers!
Every bit of information that goes through your modern Mac’s fancy multicore CPU has
to be represented as a number of one sort or another. Those numbers, in turn, are
represented by bytes of memory. Each byte consists of 8 bits, and the value of each bit
can be either 0 or 1.
You calculate the actual number as follows. Starting with the number 0, if the leastsignificant bit is 1, you add 20 (two raised to the power of zero), or 1. If the next bit is 1,
you add 21, or 2. If the third bit is 1, you add 22, or 4, and so on. When you get to the
eighth bit, if it is 1, you add 27, or 128. Once you’ve done this, the total sum is the
decimal number represented by that byte. Figure 7–1 shows some examples.
One byte
(contains 8 bits)
0
0
0
0
0
0
Decimal
number
0
0
128 + 64 + 32 + 16 + 8 + 4 + 2 + 1
0
0
0
0
1
0
1
1
1
1
1
1
1
0
=
11
1
128 + 64 + 32 + 16 + 8 + 4 + 2 + 1
1
=
1
128 + 64 + 32 + 16 + 8 + 4 + 2 + 1
= 255
Figure 7–1. How bits and bytes are used to represent numbers
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
165
In total, then, a single byte can represent a total of 256 unique numbers (or 2 to the
power of 8). To represent larger numbers, just use more bytes: 2 bytes can represent
65,536 different numbers (or 2 to the power of 16), 4 bytes allows 4,294,967,296
different numbers (or 2 to the power of 32), and so on.
Now, this might sound a bit basic, but don’t forget that bits and bytes are the
fundamental building blocks used to construct every single program on your Mac—the
operating system, all your applications, and AppleScript itself—so even though they’re
hidden away under all those higher layers, their influence is still felt.
Getting back to text… Whereas computer hardware deals only with numbers, the more
biological among us expect some decent home comforts. Although the very earliest
programmers had no choice but to toggle in raw digits on primitive mechanical
switches, as computer hardware became more powerful, they soon began to look for
better solutions. Programmers soon figured out that they could represent each character
in the alphabet as a different number, allowing computers to “understand” humanreadable text. (Well, sort of understand, anyway.) And so was born the character set.
Understanding Character Sets
A character set maps human-readable character symbols, or “glyphs,” to CPU-friendly
numbers. One early character set that is still with us today is ASCII (American Standard
Code for Information Interchange). ASCII is a small character set consisting of a mere
128 characters: uppercase and lowercase A to Z, numbers 0 to 9, a handful of arithmetic
and punctuation characters, space, tab, and special “control” characters for things like
creating line breaks, moving the text cursor, and even ringing the mechanical bell on
old-style computer consoles!
Figure 7–2 shows the full ASCII character set. As you can see, the first 32 entries are
used as special control characters—the ones you normally need to know about are
ASCII 9, the horizontal tab, and the two line break characters, ASCII 10 (line feed) and
ASCII 13 (carriage return).
Figure 7–2. The ASCII character set
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
166
CHAPTER 7: Working with Text
Despite its limitations, ASCII proved to be very popular. As the name implies, it was
designed mostly for an American, or English-speaking, audience consisting mostly of
programmers, and it contained all the characters needed by that audience. Mind you,
ASCII was not the only character set around: different companies and countries would
often develop rival character sets containing whatever characters they thought most
appropriate…although, like ASCII, they were limited to a fairly small number of
characters.
Early computers were extremely expensive and limited in power, so it was essential to
make every byte (that word again!) count. As a result, character set designers would
often use a single byte to represent each character. After all, a single byte can represent
256 different numbers—more than enough to hold all the characters in the English
alphabet, plus digits, punctuation, and a few other useful or cool symbols as well.
With the advent of low-cost microchips and the invention of the IBM PC and Apple
Macintosh, computers rapidly spread into homes and offices around the world. That
gave rise to an urgent need for operating systems such as Mac OS and Windows to
represent the characters found in the many different human languages, so new
character sets were invented to meet these local needs.
The Problem with Character Sets
Alas, all this enthusiasm for inventing more and more little character sets was creating a
real problem. With all these character sets using the same numbers, often a number that
represented a particular symbol in one set would represent a completely different
symbol in another!
Perhaps you can see the problem emerging here: if computers represent everything as
numbers, including the characters in saved text files, what happens if you create that file
using one character set and then open and display it with another?
Take a look at Figure 7–3 and Figure 7–4, which show two of the character sets that
were used on Mac OS 9 and earlier, MacRoman and MacCyrillic.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
167
Figure 7–3. The MacRoman character set
Figure 7–4. The MacCyrillic character set
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
168
CHAPTER 7: Working with Text
MacRoman was used to represent text in English and other Western languages, and
MacCyrillic was used for Russian and other Slavic texts.
The first thing you’ll notice about these character sets is that they actually have quite a
few characters in common: in fact, the first 128 characters of both character sets are
identical to the ASCII character set (I told you ASCII was popular), providing a degree of
compatibility between them. The remaining 128 symbols are mostly very different,
however, being tailored to the specific requirements of Western or Slavic languages.
For example, the phrase “ ” can be successfully represented in MacCyrillic,
but not in MacRoman, which doesn’t contain the needed glyphs. However, let’s think
about what “ ” in MacCyrillic really means in terms of bits and bytes—that is,
how each symbol is represented as a number.
Here are the characters from our text, with the corresponding MacCyrillic byte values
beneath them:
239 240 232 226 229 242 32 236 232 240
Okay, so that seems straightforward enough. But wait a moment: what if we open a
plain text file containing this text in, say, TextEdit? Well, if we know it contains
MacCyrillic-encoded text, we can tell TextEdit to interpret the bytes in the file using that
character set. However, what if we don’t know it’s Russian text, and open it as if it’s a
MacRoman-encoded file (the default on US and Western European Macs)? Here are the
previous byte values, with the corresponding MacRoman characters beneath them:
239 240 232 226 229 242 32 236 232 240
Ô
Ë ‚
Â
Ú
Ï
Ë
Clearly, “ÔË‚ÂÚ ÏË” is not the same thing as “ ”, yet both are represented
by exactly the same sequence of bytes. So, interpreting the raw bytes using the wrong
character set renders a piece of text completely incomprehensible. This makes text
worryingly fragile, especially when it is stored in something like a plain text file that
doesn’t allow you to indicate the correct character set to use as part of the file itself. If
you don’t know where the file came from, you have to guess which character set to use,
and if you guess wrong, there’s a good chance the file will display onscreen as a lot of
nonsense.
Requiring users to pick different character sets in this manner obviously wasn’t a good
start, but there was worse to come: what if a single character set didn’t contain all the
glyphs you needed to use in a particular document? As a workaround, font developers
created special symbol fonts—Mac OS 9’s Symbol and Zapf Dingbats fonts are two
classic cases—that replaced the usual alphanumeric glyphs with custom ones. But
because these fonts were using the same numerical values, 0–255, to represent wildly
different symbols from conventional fonts such as Times and Courier, all you had to do
to make a text document impossible to read was change its font settings from one font
to another!
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
169
Unicode to the Rescue!
Faced with the growing chaos of varying character sets and ad hoc workarounds for the
many limitations of those character sets, software companies finally did the sensible
thing and got together to design a permanent solution. The result was the appropriately
named Unicode character set—a single giant character set, large enough to hold all the
glyphs from all languages in common use today, with loads of room left over for future
growth as well.
NOTE: To accommodate all these different glyphs—up to a million, in fact—Unicode generally
uses multiple bytes to represent each character. You won’t need to worry about this until you start
reading and writing Unicode text files directly, so we’ll leave that discussion until Chapter 17.
Admittedly, Unicode isn’t without a few flaws of its own…it was designed by a
committee, after all. For example, many accented characters can be represented as
either a single glyph (such as é) or a combination of two glyphs, (e and ´), which can
cause unwary programs all sorts of embarrassment when trying to compare the two
(since a single digit is not, from the processor’s point of view, the same as two digits).
Smarter software will be aware of these little quirks, however, and deal with them
appropriately. And even with its imperfections, virtually everyone agrees that Unicode is
a huge step forward over the old chaos.
With every single glyph assigned to its own unique number (or code point), as long as
you know that the character set to use is Unicode, you will never have to worry about a
particular number translating to any other symbol than the one it is meant to be.
Even the font developers have gotten on board with Unicode compatibility. Although
Symbol, Zapf Dingbats, and other “special” fonts are still around today, instead of
mapping their glyphs to numbers 0–255, they now map them to the correct Unicode
code points, so that there is no risk that changing a font setting on a piece of text will
cause completely different symbols to appear.
TIP: Many Mac applications provide a palette where you can view and select characters from
anywhere in the Unicode character set. Just look under the Edit menu for a Special Characters
option. You can also obtain Unicode character charts from www.unicode.org/charts.
Introducing Text in AppleScript 2.0
With the advent of Mac OS X, Unicode took its place firmly at the center of Apple’s
operating system, and since then has spread through the vast majority of modern
desktop applications (indeed, nowadays it is pretty rare to encounter an application that
doesn’t support it unless that application is particularly old or ill-maintained).
Although AppleScript took a little while to catch up, with the release of AppleScript 2.0 in
Mac OS X 10.5, Unicode finally became the text format used throughout the entire
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
170
CHAPTER 7: Working with Text
AppleScript language. Unicode text was supported in earlier AppleScript versions (via
the Unicode text class), but it lived rather awkwardly alongside AppleScript’s older,
non-Unicode text classes (string and international text) and could be painful to work
with at times; you could not use Unicode characters within your scripts’ source code, for
example. With AppleScript 2.0, Apple replaced all the extra complexity and mess with a
single Unicode-based text class and Unicode-aware source code.
It is worth noting that some older, non-Unicode-aware Carbon applications may still use
the old string and international text classes themselves. However, as soon as nonUnicode text objects from those applications are passed to AppleScript, they are
automatically converted to AppleScript’s own Unicode-based strings. Similarly, when
passing AppleScript strings to those applications, as long the application is properly
designed, it should automatically translate back without any problem (assuming the
strings don’t contain any characters outside of the character set used by the
application).
NOTE: The main purpose of this chapter is to explain how text works in AppleScript 2.0 and
later. However, you will still often encounter older scripts written for Tiger and earlier, particularly
when looking for scripts online, so I will cover the main differences later in the chapter, in the
section “How AppleScript Text Works in Tiger.”
Now that you’ve digested a bit of background on how computers represent text data,
let’s get started on the good stuff: using text in AppleScript.
How to Write Literal Strings in AppleScript
Although you can include any characters in a string, some of them need a slightly
different treatment if you want to use them in a literal string in your script. For instance,
consider double quotes. Since a double quote is the character that specifies the start
and end of a string, how can you include quotes in a literal string? If you write the
following,
set my_text to "Choose the file named "Read Me" and open it"
AppleScript will get confused and think the literal string ends at the second double
quote ("Click on the file named "), and what comes after that won’t compile.
The error you get, shown in Figure 7–5, is almost philosophical. I’m glad that AppleScript
at least found itself…
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
171
Figure 7–5. AppleScript expected end of line but found “me”.
The error message does not say exactly what is wrong with the code, but at least it
points you in the general direction of the problem. The first step to take when an
compilation error makes no sense is to check whether you left some quote open
somewhere.
To properly include a straight double quote character (") in a string, you have to escape
it by adding a backslash character (\) in front of it. Here is the previous example again,
this time with the quote marks around the phrase “Read Me” correctly escaped:
set my_text to "Choose the file named \" Read Me\" and open it"
Here’s another problem: with the backslash acting as the special escape character in a
string literal, what do you do if you want to include the backslash character itself in a
string? For instance, if you want to display a dialog box asking users not to use the
backslash character, you will need to use it yourself. To do that, you can simply escape
it with another backslash character, like this: \\. For example, here is how you would
write C:\user\docs\readme.txt as a literal string in AppleScript:
set windows_file_path to "C:\\user\\docs\\readme.txt"
The script in Figure 7–6 displays a backslash character inside double quotes. Fancy
stuff!
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
172
CHAPTER 7: Working with Text
Figure 7–6. The script and the resulting dialog box
Another way you can include the double quote character is by simply using
AppleScript’s built-in quote variable, which contains a predefined string object with a
single double quote character in it. This might look a little odd at first because the quote
variable doesn’t go inside the quotes, of course. Using this variable, the previous script
line would look like this:
set my_text to "Choose the file named " & quote & "Read Me" & quote & " and open it"
Other characters you should know about are the tab, return, and line feed characters.
These two characters won’t give you a hard time—just the opposite; you can include
them in a string in a few ways.
The first option is to type them directly, which is simple enough.
The second way to include these characters within a literal string is by typing \r for
return and \t for tab. Both \r and \t will normally be replaced with returns (ASCII
13) and tabs (ASCII 9) as soon as you compile the script; the similar combination of
\n will be replaced with a line feed (ASCII 10) character. See Figure 7–7 and Figure
7–8 for an example.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
173
Licensed by
Jim Kilcullen
2884260
Figure 7–7. The script before it has been compiled
Figure 7–8. The script after it has been compiled
White-space characters can often be difficult to tell apart, and because white space
within strings can affect how your scripts work, you often need to know exactly what
tab, return, and/or linefeed characters your string literals contain. AppleScript Editor
allows you to disable the default behavior by selecting the “Escape tabs and line
breaks” option in the Editing panel of the Preferences window. This makes all tab and
line break characters inside literal strings appear as \t, \r, or \n. Now if you type your
script as shown in Figure 7–8 and compile it, the compiled script will appear as shown
in Figure 7–7!
The third way you can obtain tab, return, and line feed characters is by referring to the
corresponding built-in variables. AppleScript has five constants: quote (which you
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
174
CHAPTER 7: Working with Text
looked at already), space, tab, return, and (new in 10.5) linefeed. You can then use the
concatenation operator (&) to join everything together:
set my_own_menu to "coffee" & tab & "$1.15" & linefeed & "donut" & tab & "$0.65"
The Properties of Text
AppleScript’s text class defines several properties—class, length, quoted form, and
id—that allow you to obtain various bits of information from strings.
The class Property
The value of the class property is always text:
class of "Hello World!"
--> text
So, for example, if you have an object in a variable and need to find out if it is text or not,
you can use a test like this:
if class of some_object = text then
-- Do something with the text here...
else
-- It's not text, so do something else...
end if
The length Property
Because a string is made of characters, the length of the string is the number of
characters it has in it. To get the length of a string, just ask it for the value of its length
property. Here is how you do that:
length of "rope"
--> 4
The result is a number, in this case the number 4 since the string "rope" has four
characters.
The quoted form Property
The quoted form property can be used to escape a string so that it can be used safely in
a Unix shell script. I’ll discuss this property when we cover the do shell script
command in Chapter 27.
The id Property
As I discussed earlier in the chapter, each character that can appear in a string
corresponds to a unique number, or code point. In Mac OS X 10.5 and later, you can
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
175
obtain these code points by asking the string for the value of its id property. For
example:
id of "A"
--> 65
id of "
"
--> {2344, 2350, 2360, 2381, 2325, 2366, 2352,
32, 2342, 2369, 2344, 2367, 2351, 2366}
As you can see, asking for the ID of a single-character string returns a single number,
whereas a multicharacter string returns a list of numbers. The syntax is a bit odd, but it
gets the job done.
To go in the other direction, you need to use a character id ... specifier with the
following syntax:
character id integer_or_list_of_integers
For example:
character id 65
--> "A"
character id {2344, 2350, 2360, 2381, 2325, 2366, 2352, ¬
32, 2342, 2369, 2344, 2367, 2351, 2366}
--> "
"
CAUTION: When using the character id specifier, make sure it appears outside of any tell
application... blocks. Otherwise AppleScript will think you are referring to character elements in
the target application, and because scriptable applications aren’t familiar with this particular
reference form, the result would be an application error.
The Elements of Text
A large part of working with text is being able to break apart a string and manipulate
different pieces of it. AppleScript’s text class defines several types of elements for
doing this: character, word, paragraph, text, and text item. The next few sections
explain the first four; text item elements are a bit more complex, though, so I’ll cover
them later in the chapter, in the “Working with Text Item Delimiters” section.
Characters
To break a string into characters, you have to use the keyword characters to refer to all
of the string’s character elements, along with the get command:
get characters of "tic-tac-toe"
You can also drop the word get and write the following:
characters of "tic-tac-toe"
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
176
CHAPTER 7: Working with Text
Or you can write every character of ..., which has the same meaning as characters
of ...:
every character of "tic-tac-toe"
Whichever style you use, the result will be the same: a list object containing all the
characters of the string, with each character taking up one item in the list:
--> {"t", "i", "c", "-", "t", "a", "c", "-", "t", "o", "e"}
So now you know that AppleScript can split a string into characters. What you also need
to know is how to extract chunks of strings for use in your script. To put it in context,
slicing up strings and turning chunks of them into new strings is one task as a scripter
you will do all the time: figuring out what date a job is due based on the date embedded
in the file name, parsing out text files and using the information there, cleaning out
unwanted characters taken from different sources, formatting phone numbers, and so
on. The list is endless.
The first and most commonly used tool you have is the ability to extract a character from
a string by specifying its index. This method is called the index reference form, since you
refer to a character (in this case) by its position among the other characters.
An easy example is as follows:
character 5 of "AppleScript"
As you likely determined already, the result of the preceding expression is a onecharacter string, "e".
Here are a couple more examples:
character 1 of "AppleScript"
--> "A"
character 11 of "AppleScript"
--> "t"
And since I’m talking AppleScript here, and not some other, no-fun programming
language, you can also write the following:
fifth character of "AppleScript"
--> "e"
first character of "AppleScript"
--> "A"
last character of "AppleScript"
--> "t"
Let’s go back a step and look at the term last character. Of course, using this kind of
syntax is useful for that last character, or even the one before it, but what about the one
before that? You’re in luck, because AppleScript has the perfect solution! The last
character is also known to AppleScript as character –1 (that is, minus one). The reason
why this is so cool and so useful is that you can use a number to look for a specific
character by counting from the end of the string, not the beginning. Using that negativeindex reference style, you can write the following,
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
177
character –3 of "AppleScript"
which will return the character i.
For your reference, Figure 7–9 shows you different ways you can refer to different
characters in a string.
character 1, first character, 1st character
character 2, second character, 2nd character
character 3, third character, 3rd character
middle character
1
2
3
4
5
6
7
8
9 10 11
–11 –10 –9 –8 –7 –6 –5 –4 –3 –2 –1
character –3
character –2
last character, character –1
Figure 7–9. Referring to characters in a string
Looking at Figure 7–9 you can also see that the word middle is a valid reference form,
although I’ve never used that one.
Another way to refer to a character is to use the arbitrary reference form some. The
reference some character of the_string returns a random character from a string:
set the_string to "AppleScript"
set a_random_character to some character of the_string
So far, you’ve seen how to refer to individual characters by index, or all characters at
once. But what if you want to get several adjoining characters out of a larger string?
Fortunately, there is one more reference form supported by AppleScript strings: the
range reference form.
To specify a range of characters, you write the keyword characters followed by the
position of the first character, then the keyword thru, and finally the position of the last
character. For example:
characters 1 thru 4 of "tic-tac-toe"
--> {"t", "i", "c", "-"}
characters 3 thru -3 of "tic-tac-toe"
--> {"c", "-", "t", "a", "c", "-", "t"}
characters -3 thru -1 of "tic-tac-toe"
--> {"t", "o", "e"}
You’ll notice that the keyword thru isn’t fully spelled out as through. Say “thank you” to
the AppleScript team for locking the grammar police in the closet that day. As one who
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
178
CHAPTER 7: Working with Text
uses the word thru in quite a few AppleScript statements, I’m grateful. Using the full
spelling through is completely legal, however.
Working with individual character elements is sometimes useful in scripts, though it is
more common to work with larger chunks, such as words, paragraphs, or ranges of text.
So let’s move on to the next kind of text-related elements: words.
Words
As you would expect, you can also break down text into individual words. Doing this also
returns a list, but, unlike breaking text into characters, which retains the integrity of the text,
breaking text into words cleans out any characters that are considered word delimiters.
Let’s start with a little example. Type the following into a new AppleScript Editor
document and run it:
get every word of "oh my word"
The result is a list of strings, where each string contains a single word from the original
string:
--> {"oh", "my", "word"}
What you might not notice right away, you’re sure to realize with the next example:
words of "3-day forecast, starting 5/12/2009"
--> {"3", "day", "forecast", "starting", "5", "12", "2009"}
When you ask for the words of a string, you get a list of the words, but the dashes,
commas, slashes, and so on are nowhere to be seen. Punctuation marks and white
space are not considered to be words and thus are not included. Other symbols may or
may not be considered words; for example:
words of "Pay me $10"
--> {"Pay", "me", "$", "10"}
words of "Give me 100%"
--> {"Give", "me", "100"}
As you might guess, you can also ask for an individual word or a range of words:
word 3 of "You keep using that word."
--> "using"
words 5 thru -3 of "I do not think it means what you think it means."
--> {"it", "means", "what", "you", "think"}
The precise rules that AppleScript relies on when deciding what is or isn’t a word are
complicated and may vary according to system settings or Mac OS version—and the
language being used. For example, the following expression successfully breaks up
the Japanese phrase “user name” into words, even though there are no spaces in
Japanese text:
words of "
"
--> {"
", " "}
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
179
In general, although word elements can be very useful for extracting human-readable
words out of regular text, you should probably use a more precise method, such as text
ranges or text item delimiters, when you need absolute control over how a string is
broken up.
Paragraphs
Much like breaking strings into words, you can break strings into paragraphs. The logic
behind a paragraph is much simpler. The first paragraph in the string starts at the
beginning of the string and ends at the first instance of one of the following:
A carriage return character (ASCII character 13), which is the standard
line break indicator on Mac OS 9 and earlier and which is still used in
places on OS X
A line feed character (ASCII character 10), which is the standard line
break on Unix and is often used on OS X
A carriage return character followed by a line feed character, which is
the standard line break on Windows
If you have only one paragraph (and there’s always at least one paragraph, even if the
string is empty!), then that one paragraph ends at the end of the string. If you have more
than one paragraph, then the second paragraph starts right after the first line break and
ends right before the next one, and so on. The last paragraph ends at the end of the
string.
Take, for example, Script 7–1. It starts with a simple string that contains five paragraphs
(one of which is empty) and asks AppleScript to return every paragraph. The result is a
list in which every list item is a string that contains one paragraph from the original text.
Script 7–1.
set my_string to "This is a line
The next line is here
I'm third
Last paragraph"
every paragraph of my_string
--> {"This is a line", "The next line is here", "I'm third", "", "Last paragraph"}
Text Ranges
Earlier you saw how to extract a sequence of characters as a list of single-character
strings, but what if you want to extract them as a single string instead?
A common novice approach is to extract a list of characters and then use AppleScript’s
as operator to convert, or coerce, it into a single piece of text, like this:
(characters 5 thru 7 of "tic-tac-toe") as text -- Not a good way to get text ranges
--> "tac"
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
180
CHAPTER 7: Working with Text
Although this approach may appear to do what you want, it isn’t very efficient and can
easily lead to unexpected errors, as you will discover later in the chapter when I discuss
how list-to-string coercions actually work.
Fortunately, AppleScript provides a far better way to extract one string from another, by
referring to a string’s text elements. This type of reference always has the following form:
text start_position thru end_position of the_string
For example:
set the_string to "Necessity is the mother of taking chances."
set sub_string to text 9 thru 18 of the_string
--> "y is the m"
This is a particularly useful way to reference text, so let’s look at a quick practical
example.
Let’s say that you have a file name, "JB445091_UTFg12.zip", and you need to extract the
client’s account number, which is the six-digit number starting from the third character.
Let’s start by assigning the string to a variable so that it is easier to work with:
set job_file_name to "JB445091_UTFg12.zip"
For this exercise, the file name is given as a literal string. In a larger working script, you
would probably retrieve it from the Finder using a get command.
The first step in obtaining the client’s account number is to refer to the text range that
starts at character 3 and ends on character 8 (that’s six characters in all, since the start
and end indexes are inclusive):
set account_number_string to text 3 thru 8 of job_file_name
Once you’ve extracted a string containing only the account number information, the
second and final step is to coerce this string into an integer by using the as operator:
set account_number to account_number_string as integer
If you prefer, you can combine the last two lines into one:
set account_number to (text 3 thru 8 of job_file_name) as integer
The expression in the first set of parentheses produces a string, and as integer at the
end coerces that string into an integer.
Now run the script in AppleScript Editor. The result should be the client’s account
number, 445091.
Another point I will discuss later is that the error-free execution of the script depends on
the extracted characters being all digits. You’ll learn more about that when I talk about
coercing text later in the chapter.
As you can see, text ranges are already pretty useful to work with, but they have one
more trick up their sleeves. You already know how to extract a range of text from one
character to another, but what if you want to start and finish on a whole word or
paragraph?
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
181
As you found out in Chapter 5, scriptable applications often allow you to identify the
start and end positions using “mini” references to the exact elements you want to begin
and end on. The good news is that AppleScript strings also allow you to do this: you can
begin and/or end on a character (the default), a word, or a paragraph.
For example, let’s say you want to extract all the text that lies between two words
(inclusive). Here is how you do it:
set the_string to "Necessity is the mother of taking chances."
set sub_string to text (word 3) thru (word -2) of the_string
--> "the mother of taking"
Pretty slick, huh? You can use the same technique when referring to character, word,
and paragraph ranges too, although I find it is most often useful when working with text
ranges.
At this point, we have covered almost all the elements of AppleScript strings. We have
one more type of element, text item, still to cover, but before we get to that, let’s look
at the more general features that AppleScript provides for working with strings.
Operators and Commands
Extracting information from strings via their properties and elements is obviously useful,
but if that was all we could do with strings, we’d probably get rather bored with them
before very long. Happily, AppleScript provides a number of commands and operators
for manipulating strings in other ways, so we’ll look at these next.
Joining Strings
You already saw the concatenation operator at work in Chapter 3, but now you’ll look at
how it operates on strings in a bit more detail.
Concatenating two strings always returns a string result. For example:
"Hello, " & "World!"
--> "Hello, World!"
That makes sense. What else would it return? Well, try the following in a new script
window:
set the_price to "$" & 6
The result is "$6".
The difference here is that you concatenated a string to a number. AppleScript took the
liberty to coerce the number into text for you, so the result is the same as if you had
treated the 6 as text in this way:
set the_price to "$" & "6"
You get the same result.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
182
CHAPTER 7: Working with Text
However, let’s see what happens when you switch places:
set the_price to 6 & " Dollar"
The result this time is different. Because the first operand (the item you operate on) is a
number and not a string, AppleScript figures that returning a list is safer than returning a
string. The result, then, is a list of two items, a number and a string:
--> {6, " Dollar"}
To prevent that from happening, you have to use the coercion operator, as, to convert
the number to a string yourself.
The as operator converts an object of one class into an object of another class. In this
case, you should first coerce the number (which is an object of class integer) to a string
(an object of class text), like this:
set the_price to (6 as text) & " Dollar"
Now the result is a single string—"6 Dollar"—just as you wanted.
CONCATENATE WITH CARE
Take care! A common mistake here is to join the two values using the following:
6 & " Dollar" as string
This may seem to work okay sometimes, but it hides a nasty bug because it works by first creating a twoitem list, {6, "Dollar"}, and then coercing that list to a string. If AppleScript’s text item
delimiters property (which you’ll meet shortly) is set to any value except an empty string, you’ll find
extra characters mysteriously inserted into the result! To avoid such unpleasant surprises, always write it
as (6 as string) & " Dollar" instead.
Comparing Strings
What about the other operators? Well, many operators compare one string to another.
These operators are =, ≠, <, ≤, >, and ≥—otherwise known as is equal to, is not equal
to, is less than, is less than or equal to, is greater than, and is greater than
or equal to.
Let’s start with the simple ones: comparing two strings for equality. It’s easy to
understand how you can see whether strings are equal; consider the following
operations. This one,
"Ice cream" = "carrot"
returns false. And this one,
"Me" ≠ "You"
returns true.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
183
Incidentally, AppleScript allows each of these operators to be written in any of several
ways: as symbols, words, or phrases. This makes no difference to how your script runs,
but it does allow you to write your code in whichever style you think reads best. Here are
the various alternatives, or synonyms, AppleScript provides for the = and ≠ operators:
"Ice
"Ice
"Ice
"Me"
"Me"
cream"
cream"
cream"
is not
is not
is "carrot"
equals "carrot"
is equal to "carrot"
"You"
equal to "You"
TIP: Operator synonyms are a neat feature that can help to make your code easier to read. You
can find a summary of all available operator synonyms in Chapter 13.
Licensed by
Jim Kilcullen
2884260
Let’s look at some more string comparisons. How about the following statement?
"555-1212" = "5551212"
--> false
Or the following one?
"ASCII" = "ascii"
--> true
The result of the first operation is false because the first operand has an extra hyphen in
it, whereas the result of the second one is true because AppleScript normally ignores
case when comparing two strings. AppleScript makes a number of assumptions by
default about what characteristics of the text you want to consider or ignore while
comparing text. You can overrule these assumptions with special considering and
ignoring clauses that allow you to ignore or consider certain conditions. More details on
considering and ignoring clauses are coming up shortly.
Much like the is equal to and is not equal to operators, the is less than and is
greater than operators always return a result as a Boolean.
To determine in a script whether one string comes before another string, use the is
less than operator, which can be written in any of several ways:
"a"
"a"
"a"
-->
comes before "b"
< "b"
is less than "b"
true
Similarly, the is greater than operator checks whether the first parameter is greater
than the second or appears later in the sorting chain:
"a"
"a"
"a"
-->
comes after "b"
> "b"
is greater than "b"
false
Use the is greater than or equal to operator to see whether one value is either the
same as or greater than another:
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
184
CHAPTER 7: Working with Text
"a" ≥ "b"
"a" is greater than or equal to "b"
--> false
And you can use the is less than or equal to operator to see whether one value is
the same as or less than the other:
"a" ≤ "b"
"a" is less than or equal to "b"
--> true
You may be wondering exactly how AppleScript decides if one string comes before or
after another string. The answer is…it’s a bit complicated.
With old-fashioned character sets such as MacRoman, one character is considered less
than or greater than another character depending on whether the first character appears
before or after the second one in the MacRoman character table. Unicode is much more
sophisticated, however, and decides the ordering based on meaning as well as physical
position in the Unicode character set.
For example, consider three characters, 0, ?, and A. In the ASCII character set, ? is at
code point 63, so it comes after 0, which is at code point 48, but comes before A, which
is at code point 65. In Unicode, the first 128 characters are also based on ASCII, so
these characters occupy exactly the same code points:
id of "0" --> 48
id of "?" --> 63
id of "A" --> 65
However, when you try to compare them as Unicode strings, you will find that ?—along
with other punctuation marks—actually comes before both 0 and A, although 0 still
comes before A as before:
"?" < "A" --> true
"?" < "0" --> true
"0" < "A" --> true
A full discussion of how Unicode determines which characters come before or after
other characters is beyond the scope of this book. You might want to research Unicode
sorting rules on your own if you are going to perform tasks such as sorting a list of
strings into order, as they will affect the final result. In general, though, the Unicode rules
are based on what human users would consider a common-sense sorting order, so it
seems quite natural for AppleScript to follow them.
Checking for Strings Within Strings
Several operators can be used to check for strings within other strings. These operators
are starts with, ends with, contains, and is in.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
185
As their names suggest, the starts with and ends with operators check whether a
string appears at the start or end of another string, respectively, and return true or false
as the result. For example:
"Don't let schooling interfere with your education." starts with "Don't let school"
--> true
"Action speaks louder than words but not nearly as often." ends with "words"
--> false
The contains operator checks whether the string given as the second operand appears
anywhere in the string that is the first operand:
"Name the greatest of all inventors. Accident." contains "vent"
--> true
The is in operator does about the same thing, only it checks whether the first string
appears within the second:
"necessary evil" is in "Work is a necessary evil to be avoided."
--> true
As with the comparison operators, the result of containment operations can be
influenced by considering and ignoring clauses, so let’s look at those next.
Considering and Ignoring Attributes
AppleScript allows you to consider or ignore various attributes of text when doing string
comparisons. These attributes are (in alphabetical order) case, diacriticals, hyphens,
numeric strings, punctuation, and white space. By default, when comparing strings,
AppleScript ignores case and numeric strings but considers the rest.
To change how strings are compared, you have to wrap your comparison tests in a
considering or ignoring statement, depending on your intention. These statements
have the following syntax:
considering attribute [, attribute ... and attribute ] ¬
[ but ignoring attribute [, attribute ... and attribute ] ]
-- One or more statements...
end considering
ignoring attribute [, attribute ... and attribute ] ¬
[ but considering attribute [, attribute ... and attribute ] ]
-- One or more statements...
end ignoring
As you can see, you can specify the attributes to be considered and those to be ignored
either in separate statements, or combined into one statement if you want to specify
both at the same time. You can specify as few or as many attributes as you want; any
attributes that are omitted remain at their current settings.
Let’s start with a simple example: comparing two strings for equality. The default
AppleScript behavior is to ignore the case of characters, so asking AppleScript to
consider the case of characters will yield a different result. Simply stating the following,
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
186
CHAPTER 7: Working with Text
"A" = "a"
returns true, and since AppleScript ignores the case of characters by default, the
following statement returns true as well:
ignoring case
"A" = "a"
end ignoring
If you want to take the case of the strings into consideration, then you need to wrap the
comparison test in a considering case ... end considering block, like this:
considering case
"A" = "a"
end considering
The result of the preceding script snippet is false.
In a recent project, I had to add to a system a feature that would determine whether the
content of a Microsoft Excel sheet had changed. The solution was to save every
worksheet as a text file and then compare the most recent text file with the older version
of that file. Initially, I used the following line:
set files_match to (read file_a) = (read file_b)
The statement simply compares two strings that are returned from the read command
(which you will explore in depth later in this book). The problem with this solution is that
if someone simply fixed a capitalization problem in a worksheet, AppleScript would still
think the text of the files is identical. The script was retrofitted with the considering case
clause, like this:
considering case
set files_match to (read file_a) = (read file_b)
end considering
This time, even a simple change of capitalization would show.
The diacritical, hyphen, and punctuation consideration attributes work slightly
differently. Each of these refers to a set of special characters that can be ignored when
comparing strings. All are considered by default, so using them in a considering clause
won’t normally change the result, but using them in an ignoring clause will.
The ignoring diacriticals clause allows you to ignore any accent marks so that the
following statement returns a true result:
ignoring diacriticals
"Résumé" = "Resume"
end ignoring
--> true
The ignoring hyphens clause allows you to ignore hyphens in the text:
ignoring hyphens
"1-800-555-1212" = "18005551212"
end ignoring
--> true
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
187
CAUTION: In Mac OS X 10.5 and earlier, the ignoring hyphens clause ignores only hyphen
(minus) characters. In 10.6 and later, typographical dashes such as an en dash or em dash are
also ignored.
The ignoring punctuation clause allows you to ignore punctuation marks. Here’s an
example:
ignoring punctuation
"That's all, right? Now!" = "Thats all right now."
end ignoring
--> true
NOTE: The Unicode character set defines which characters are punctuation and which aren’t.
You can find out about these and other Unicode rules at www.unicode.org/standard.
The ignoring white space clause allows you to ignore spaces, tabs, line feeds, and
return characters when comparing strings:
ignoring white space
"Space craft" = "Spacecraft"
end ignoring
--> true
The considering numeric strings clause is useful when comparing strings that contain
a mixture of text and numbers; for example:
"Chapter 5.pdf" comes before "Chapter 10.pdf"
--> false -- Not the answer you wanted!
considering numeric strings
"Chapter 5.pdf" comes before "Chapter 10.pdf"
end considering
--> true
Considering numeric strings is also very useful when comparing version numbers.
Because application version numbers are conveyed as strings and commonly contain
multiple decimal points (for example, 1.4.2) or more than one digit per part (for example,
2.13.9), converting them into a number often isn’t possible, or safe. For that reason,
version numbers are best compared as strings.
Take, for instance, these two version numbers (expressed as strings): "1.5.8" and
"1.5.10". If looked at simply as sequences of characters, the “8” in the first string is
greater than the “1” at the same position in the second string. Therefore, the following
script returns true:
"1.5.8" > "1.5.10"
--> true
However, in the world of numbers, we know that 10 comes after 8, so the result we
actually want is false. Considering numeric strings will correct that, as you can see here:
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
188
CHAPTER 7: Working with Text
considering numeric strings
"1.5.8" > "1.5.10"
end considering
--> false
Using a single considering or ignoring statement might be sufficient for your needs, but
what if you need to specify more than one attribute? For that you can use multiple
parameters and even nest clauses.
Say you’re writing a quick-fire question-and-answer game. Although you need the
words to be correct, you want to be lenient when it comes to case, diacriticals,
dashes, and spaces.
Here is how you can evaluate the accuracy of the answer:
ignoring case, diacriticals, hyphens and white space
set is_answer_correct to user_answer = actual_answer
end ignoring
This will ensure that if the expected answer is “El Niño”, the responses “elnino”, “El
nino”, “Elñino”, and “El-Nino” will also register as correct.
What if you do want to consider the case of the answer but also want to give some slack
over the rest? Your statement would look like this:
considering case but ignoring diacriticals, hyphens and white space
set is_answer_correct to user_answer = actual_answer
end considering
You can also nest considering and ignoring statements inside one another; for
example:
considering case
ignoring diacriticals
ignoring hyphens and white space
set is_answer_correct to user_answer = actual_answer
end ignoring
end ignoring
end considering
One final thing to remember when using considering and ignoring blocks: if you send a
command from inside a considering or ignoring statement, the attributes you specify
might also affect the code that handles the command. For example:
offset of "s" in "AppleScript"
--> 6
considering case
offset of "s" in "AppleScript"
end considering
--> 0 -- A lower-case "s" wasn't found!
Whether or not this happens depends on the particular handler you called. Most
scriptable applications and scripting additions always ignore case and consider
everything else, and simply ignore any attributes specified by your script (the Standard
Additions offset command is one of the exceptions). On the other hand, user-defined
handlers that appear in scripts are always affected:
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
189
on is_pdf_file(file_name)
return file_name ends with ".pdf"
end is_pdf_file
set file_name to "DN301002.PDF"
considering case
is_pdf_file(file_name)
end considering
--> false -- Oops!
This can cause hard-to-trace bugs in larger scripts where user-defined handlers that
perform text-related operations are called from within considering/ignoring statements.
If you need to, you can protect sensitive code against this problem by wrapping
comparison and containment operations in their own considering/ignoring blocks that
specify exactly the attributes you need at the time; for example:
on is_pdf_file(file_name)
ignoring case but considering diacriticals, hyphens, punctuation and white space
return file_name ends with ".pdf"
end ignoring
end is_pdf_file
set file_name to "DN301002.PDF"
considering case
is_pdf_file(file_name)
end considering
--> true
The count Command
In addition to the length property, you can also use the count command to get the
number of characters of a string. For example:
count "Hello World!"
--> 12
You can even use the optional each parameter to indicate exactly which class of element
you want to count (without it, the default value is item, which in this case means each
character):
count "Hello World!" each word
--> 2
Personally, though, I prefer to use a reference to the desired elements instead—it gives
the same answer but makes the code easier to read:
count words of "Hello World!"
--> 2
The offset Command
The offset command, which is defined in the String Commands suite of the Standard
Additions dictionary, is useful for figuring out where a certain substring starts in
another string.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
190
CHAPTER 7: Working with Text
The result of the offset command is an integer that indicates the position of the first
instance of the substring in the main string, or 0 if the substring is not found.
Here’s a simple example of the offset command:
offset of "@" in "steve@apple.com"
--> 5
Script 7–2 uses the offset command to extract the domain name from a valid e-mail
address.
Script 7–2.
set
set
set
-->
the_email_address to "info@store.apple.com"
the_offset to offset of "@" in the_email_address
the_domain to text (the_offset + 1) thru -1 of the_email_address
"store.apple.com"
Coercing to and from Text
To convert an object of one class into an object of another class, you use a coercion.
Some coercions occur automatically when needed—for example, when using the
concatenation operator, &, to join a number onto the end of a string, AppleScript first
coerces the number into a string for you:
"Joe" & 90 -- The second operand is automatically coerced to text
--> "Joe90"
Other times, you can use the as operator to coerce objects yourself; for example:
42 as text
--> "42"
AppleScript supports a number of coercions for text objects.
You can, of course, coerce any text object to text:
"Hello World!" as text
--> "Hello World!"
In other words, the result of coercing text to text is the text object you already had. That
might not seem useful, but it’s good to know that AppleScript won’t mess with your text
when you do this. For example, if your script has a variable that ought to contain text but
might be a number or something else, just coerce its value to class text and then you
can be 100 percent sure.
AppleScript also allows you to coerce text to boolean, integer, real, alias, and POSIX
path, as long as the content of the string is appropriate for that class:
"true" as boolean
--> true
"false" as boolean -- Or any string other than "True"
--> false
"16" as integer
--> 16
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
191
"-3.3333" as real
--> -3.3333
"Macintosh HD:Applications:TextEdit.app" as alias
--> alias "Macintosh HD:Applications:TextEdit.app:"
"/Applications/TextEdit.app" as POSIX file
--> file "d1:Applications:TextEdit.app"
If AppleScript is unable to coerce the string to the desired class, a coercion error
(number –1700) will occur:
--"forty-two" as integer
-- Error: Can't make "forty-two" into type integer.
You can also coerce a string to a single-item list:
"Hello World!" as list
--> {"Hello World!"}
Any objects of class boolean, integer, real, alias, or POSIX path can be coerced to
class text:
true as text
--> "true"
"false" as text
--> "false"
16 as text
--> "16"
-3.3333 as text
--> "-3.3333"
(alias "Macintosh HD:Applications:TextEdit.app") as text
--> alias "Macintosh HD:Applications:TextEdit.app:"
(POSIX file "/Applications/TextEdit.app") as text
--> "d1:Applications:TextEdit.app"
NOTE: Coercing an alias or POSIX file object to text always gives a colon-delimited HFS file path.
If you want a slash-delimited POSIX file path instead, you should ask the object for the value of
its POSIX path property instead. We’ll cover these objects in detail in Chapter 17.
In addition, there are a few other classes you can coerce to text: date, class, and
constant (although you cannot coerce them in the other direction). For example, here’s
how you coerce a date to text:
set the_date to date "Tuesday, September 15, 2009 19:03:55"
the_date as text
--> "Tuesday, September 15, 2009 19:03:55"
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
192
CHAPTER 7: Working with Text
TIP: Chapter 9 will explain how to convert between dates and text in much more detail.
And here are some examples of coercing class names (document, Wednesday) and a
constant (no):
document as text
--> "document"
Wednesday as text
--> "Wednesday"
no as text
--> "no"
Finally, you can coerce a list to text as long as the list contains text objects, or objects
that can be coerced to text. If the list contains only a single item, the result is
straightforward:
{"That's no ordinary rabbit!"} as text
--> "That's no ordinary rabbit!"
If the list contains multiple items, however, things become a little more complex because
text item delimiters become involved. I will discuss how list-to-text coercions work in
more detail later in the next section.
Working with Text Item Delimiters
Yet another AppleScript pearl, text item delimiters, is a property built into
AppleScript, and it’s useful for a whole range of text manipulations.
The text item delimiters property is used in two situations: when splitting a string into
a list of smaller strings and when coercing a list of strings into one big string.
Splitting Strings with Text Item Delimiters
AppleScript allows you to split a string by searching for a substring (or several
substrings) and breaking the string wherever the substring is found. To do this, you use
the text item element defined by AppleScript’s text class and the text item
delimiters property, which is defined by AppleScript itself and can be accessed from
anywhere in the script.
By default, AppleScript’s text item delimiters property is set to {""}, which means
asking for every text item element of a string is the same as asking for every character
of a string. Where things start to get exciting is when you set AppleScript’s text item
delimiters property to a different value.
Let’s take a phone number, 800-555-1212, and see what happens when you change
AppleScript’s text item delimiters property to "-".
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
193
Start a new script window, and enter the following script text:
set text item delimiters to "-"
get every text item of "800-555-1212"
Run the script, and the result will be the following list of strings:
--> {"800", "555", "1212"}
Figure 7–10 shows how this works.
Licensed by
Jim Kilcullen
2884260
Figure 7–10. Breaking up a string after setting the text item delimiters property to a hyphen
As you can see, the delimiter substrings themselves are discarded, and anything in
between them ends up as items in the resulting list.
Splitting strings into lists is one way you can use text item delimiters, but you can also
use them within larger references. For example, Script 7–3 shows another way to extract
the domain name from an e-mail address, this time by using text item delimiters to split
the string on the “@” symbol.
Script 7–3.
set
set
set
-->
the_email_address to "info@store.apple.com"
text item delimiters to "@"
the_domain to text item -1 of the_email_address
"store.apple.com"
When referring to a string’s text elements, a really neat trick is to use a reference to a
text item as the start or end point. Script 7–4 shows how to extract the parent folder
from a POSIX path string by extracting a substring that goes from the start of the original
string up to (but not including) the final slash character.
Script 7–4.
set
set
set
-->
the_path to "/Users/hanaan/Work/todo.txt"
text item delimiters to "/"
the_parent_path to text 1 thru (text item -2) of the_path
"/Users/hanaan/Work"
As you can see, the starting point for the text range is given as 1—that is, character 1.
The end point for the range is specified by a relative reference, text item -2, that
identifies the second-to-last text item in the path string (in this case, “Work”). The result
is a string that contains all the text that was found at the start and end points plus
everything in between.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
194
CHAPTER 7: Working with Text
By default, text item delimiters are case insensitive but match everything else exactly.
For example:
set text item delimiters to "e"
text items of "PLEASE read my résumé!"
--> {"PL", "AS", " r", "ad my résumé!"}
However, you can use considering and ignoring statements to make them consider
case or ignore diacriticals as well:
set text item delimiters to "e"
considering case and diacriticals
text items of "PLEASE read my résumé!"
end considering
--> {"PLEASE r", "ad my résumé!"}
set text item delimiters to "e"
ignoring case and diacriticals
text items of "PLEASE read my résumé!"
end ignoring
--> {"PL", "AS", " r", "ad my r", "sum", "!"}
One thing you may have noticed about the text item delimiters property is that the
default value is a list object containing a single string. Usually you only want to split a
string on a single delimiter string. In that case, you can assign the delimiter string
directly to the property (for example, "/"), although you can wrap it up as a single-item
list if you prefer ({"/"}). In Mac OS X 10.6 and later, however, you can also split a string
using multiple delimiters.
Script 7–5 uses this new feature to clean up phone numbers by removing any
parentheses, spaces, and hyphens.
Script 7–5.
set the_phone_number to "(800) 555-1212"
set text item delimiters to {"(", ")", "-", " "}
set the_list to text items of the_phone_number
Create a new document in AppleScript Editor, and type in the code as shown. When you
run it, the result will be the following list of substrings:
--> {"800", "", "555", "1212"}
In case you’re wondering, the second item in the list comes from between the closing
parenthesis and the space character that immediately follows it. Because there are no
non-delimiter characters between these two delimiters, the result is an empty string.
The script isn’t complete yet—we still need some way of joining the remaining pieces
back together, but it’s a good start. The next section will look at how we can combine
this list back into a single string.
Combining List Items into a Single String
The other function of the text item delimiters property is to provide padding between
items when coercing a list into a string.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
195
Let’s finish the code started in Script 7–5. Script 7–6 adds the final two lines: the first to
set the current text item delimiter to an empty string; the second to coerce the list back
into a single string.
Script 7–6.
set the_phone_number to "(800) 555-1212"
set text item delimiters to {"(", ")", "-", " "}
set the_list to text items of the_phone_number
set text item delimiters to ""
set the_cleaned_phone_number to the_list as text
Now when you run the script, the result will be as follows:
--> "8005551212"
As you can see, when the text item delimiters property is set to an empty string, the
list items just squish together.
Let’s try another example. Script 7–7 shows how to turn a list of strings into a single
string with each item separated by a comma and a space.
Script 7–7.
set shopping_list to {"bread", "milk", "butter", "cream", "Wensleydale cheese"}
set text item delimiters to ", "
set shopping_text to shopping_list as text
display dialog "Remember to buy " & shopping_text & "."
Figure 7–11 shows the assembled text that appears in the dialog box when the script is run.
Figure 7–11. The assembled string displayed in a dialog box
As you may have noticed, although most of our delimiters have been single-character
strings, multicharacter strings also work. In Script 7–8, the text item delimiters
property is set to the string "mississippi":
Script 7–8.
set text item delimiters to "mississippi"
set the_secret_message to ¬
"memississippiet mississippime mississippiamississippit fimississippive"
set the_items to text items of the_secret_message
set text item delimiters to ""
set the_message to the_items as string
-->"meet me at five"
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
196
CHAPTER 7: Working with Text
One more thing before we move on: generally, getting and setting the text item
delimiters property is pretty straightforward, but there is one gotcha you need to watch
out for. Any time you need to address the text item delimiters property from inside an
application’s tell block, you must make it clear to AppleScript exactly whose text item
delimiters property you are referring to.
To demonstrate, try running the following script:
tell application "Finder"
set text item delimiters to ":"
end tell
The result of this will be an error: “Finder got an error: Can’t set text item delimiters to
":".” That’s because, unless you tell it otherwise, AppleScript assumes you are referring
to a property named text item delimiters in the target application. Since most
applications, including the Finder, don’t have a property by this name, they will throw an
error to let you know this.
Fortunately, the solution is a simple one: just make it clear that you are referring to a
property of AppleScript itself. To do this, you need to identify the AppleScript object,
which is where the text item delimiters property is found; for example:
tell application "Finder"
set AppleScript's text item delimiters to ":"
end tell
Now the script will successfully set AppleScript’s text item delimiters property to the
desired value, exactly as you intended.
Finding and Replacing Text
One use of the text item delimiters property is to perform a simple search and
replace on strings inside AppleScript. You do this by setting the value of the text item
delimiters property to the text you want to replace and splitting the text you want to
search in into a list. This will remove the search text. Next you set the text item
delimiters property to the replacement text and combine the list back into a string.
For this example, we will look at a simple way to take template text containing
placeholders and personalize it. Imagine that you have a string that is part of some legal
text you need to insert at the end of a document. The text was prepared in advance with
the placeholders and looks like this: “Let it be known that [company] is responsible for
any damage any employee causes during [company]’s activity while in the conference.”
Let’s imagine that this text is stored as a string in the variable form_text. You also have
another variable, called company_name, which will be set to the string "Disney Inc." for
these purposes.
Script 7–9 shows the code that will replace the text "[company]" with the specified
company name.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
197
Script 7–9.
1. set form_text to "Let it be known that [company] is responsible for any damage" ¬
& " any employee causes during [company]'s activity while in the conference."
2.
3.
4.
5.
6.
7.
set text item delimiters to "[company]"
set temporary_list to text items of form_text
set text item delimiters to "Disney Inc."
set finished_form to temporary_list as text
set text item delimiters to ""
return finished_form
You can study the intermediate workings of this script by temporarily inserting a return
temporary_list statement after line 5. The value of the temporary_list variable is as
follows:
--> {"Let it be known that ",
" is responsible for any damage any employee causes during ",
"'s activity while in the conference."}
Note how the "[company]" placeholder is omitted from the temporary list shown
previously.
Now, remove the temporary return statement so that the rest of the script can run as
well. The value of the finished_form variable is this text: “Let it be known that Disney
Inc. is responsible for any damage any employee causes during Disney Inc.’s activity
while in the conference.”
How AppleScript Text Works in Tiger
The transition to 100 percent Unicode support in Leopard was undoubtedly the biggest
change to occur in the AppleScript language since it was first released in 1993. Sure, the
implementation of AppleScript may have changed a lot since then, moving from 68K
processors to PPC and then Intel, jumping from Mac OS 9 to Mac OS X, and growing
64-bit support along the way.
None of these behind-the-scenes changes really affected how scripters interacted with
AppleScript, though: scripts written even on early versions of AppleScript continued to
work, with perhaps just an occasional quick recompile needed.
With the switch to full Unicode, however, AppleScript finally decided to shake things up.
Some scripts that worked for years on AppleScript 1.x suddenly required alterations to
run smoothly on AppleScript 2.0; although the transition was remarkably smooth
considering the amount of change involved, some non-backward-compatible alterations
were pretty much inevitable.
As older operating systems such as Tiger fade away, this will become less of a concern
for users; however, there are still many older AppleScripts available online that may not
have been updated for Leopard. To help you to understand and update old scripts, the
next few sections briefly discuss the main “highlights” of working with AppleScript text
in Tiger and earlier.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
198
CHAPTER 7: Working with Text
The Many Different Classes of Text
Before Leopard, AppleScript provided multiple classes to describe text objects: string,
styled text, international text, and Unicode text. As you might imagine, this could
be a bit of a mess to work with at times.
AppleScript’s original string class could only represent a limited range of characters.
When dealing with older applications that don’t support Unicode, Mac OS X picks an
old-style character set to be your “primary encoding.” Your system’s language settings
determine the exact character set used—for example, for English and most other
European languages, the MacRoman character set, which contains 256 characters, is
used. If your system language is Japanese, then the primary encoding will be the
MacJapanese character set, which contains several thousand characters. In Tiger and
earlier, this primary encoding was used by AppleScript objects of the string class, and
also for your source code.
The styled text class was a bit different. Although it was based on your primary
encoding, it also held font information. This meant that if your primary encoding didn’t
contain a particular glyph, a styled text object might still be able to represent it if it
could find it in one of the non-Unicode “special symbols” fonts (Symbol, Zapf
Dingbats, etc.). This allowed it to represent a larger range of characters than the
string class, although still far fewer than could be found in Unicode. One of the quirks
of styled text objects was that when you ask them for their class, the result would be
string, which meant you could never be entirely sure if you were dealing with a
regular unstyled string or a styled one.
The international text class was Apple’s own attempt to come up with a Unicode-like
standard for representing text, back before Unicode itself was created. Once Unicode
came along, this format quickly became redundant, although it lingered for a while in
some older applications that had adopted it before Unicode was available.
Finally, the Unicode text class was AppleScript’s response to the growing availability of
Unicode support in the classic Mac OS, allowing scripts to work directly with Unicodebased text. (The new text class that appears in Mac OS X 10.5 and later is equivalent to
the old Unicode text class.) This was a later addition to AppleScript, which probably
goes some way toward explaining the multitude of other classes that had already
appeared by the time it was introduced.
Working with the Various Text Classes
As AppleScript source code in Tiger and earlier was based on the system’s primary
encoding, any literal strings in your script would be of the string class; for example:
set the_text to "it's all text"
class of the_text
--> string
Text coming from other sources such as scriptable applications could be in any format,
depending on whether or not the application supported Unicode, needed to work with
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
199
characters outside the user’s primary encoding, and so on. You could also coerce text
from one text class to another; for example:
set the_text to "it's all text" as Unicode text
class of the_text
--> Unicode text
Coercing text of class Unicode text to the string class would also work (the result was
actually a styled text object), although any characters that couldn’t be represented
would be replaced with “?” characters.
Comparing strings of different classes but with the same content returns a true result;
for instance:
set string_text to "it's all text"
set unicode_text to "it's all text" as unicode text
string_text = unicode_text
--> true
However, if you want to check that a given object is some kind of text, but aren’t sure if
its class is string or Unicode text, then you have to check for both possibilities. For
example:
if class of the_text is in {string, Unicode text} then
-- Do something with the text here...
end if
If you need the script to run on Mac OS X 10.5 and later as well as on 10.4 and earlier,
you also have to check for a third option, text, as that is the class of all text objects in
10.5 onward:
if class of the_text is in {text, string, Unicode text} then
-- Do something with the text here...
end if
Another significant difference between string and Unicode text objects is in how the
less-than and greater-than comparisons work. As discussed earlier, Unicode defines its
own logical rules that determine whether one character comes before or after another,
regardless of their physical position in the Unicode character set. With older character
sets such as MacRoman, character order is decided purely by position. For example,
("?" as Unicode text) < ("0" as Unicode text) -- Comparing Unicode characters
--> true
but,
"?" < "0" -- Comparing MacRoman characters
--> false
The final difference I’ll mention here is in how splitting text with text item delimiters
works. Strings of class Unicode text respect the script’s current considering/ignoring
case and diacriticals attributes when getting text item elements. For example:
set text item delimiters to "e"
ignoring case and diacriticals
text items of ("PLEASE read my résumé!" as Unicode text)
end ignoring
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
200
CHAPTER 7: Working with Text
--> {"PL", "AS", " r", "ad my r", "sum", "!"}
This matches the behavior of text in AppleScript 2.0.
When dealing with objects of class string, however, all considering/ignoring attributes
are ignored and an exact, case-sensitive match is performed instead:
set text item delimiters to "e"
ignoring case and diacriticals -- This won't work on text of class string
text items of "PLEASE read my résumé!"
end considering
--> {"PLEASE r", "ad my résumé!"}
If you need text item delimiters to perform case-insensitive matching in Tiger or earlier,
you need to make sure your text is coerced to class Unicode text before you begin.
Similarly, if you want to perform a case-sensitive match but aren’t quite sure what class
the text is, you’ll want to enclose the code in a considering case ... end considering
block just to be sure.
There are several other differences between the string and Unicode text classes as
well—for example, how word elements are determined and which coercions are
supported—but because these differences are less important, we won’t bother going
into them here.
TIP: If you do need to support Tiger and earlier, refer to the original AppleScript Language Guide
included in Apple’s Developer Tools for more information. This mainly covers AppleScript 1.3.7,
but much of the content still applies to Tiger’s AppleScript, and a list of more recent changes can
be found in the AppleScript Release Notes on Apple’s developer site
(http://developer.apple.com).
The ASCII number and ASCII character Commands
Prior to Mac OS X 10.5, AppleScript provided two Standard Additions commands, ASCII
number and ASCII character, for converting single-character strings to and from their
corresponding code points. However, as their names suggest, these commands did not
support Unicode text, and were only good for working with ASCII and other single-bytebased character sets.
The ASCII number command takes a one-character string as its parameter and returns a
number from 0 to 255 that indicates its position in the MacRoman character table (or
whatever the user’s primary encoding is). For instance, the statement ASCII number
space will return 32, which is the code point of the space character.
The opposite command is ASCII character, which accepts a number from 0 to 255 as
its parameter and returns the character for that code point. For instance, the statement
ASCII character 36 will return the one-character string $.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
201
Try the following script:
display dialog "I love the big " & ASCII character 240
While executing the script, AppleScript evaluates the ASCII character 240 command.
Assuming your primary encoding is MacRoman, this returns a string containing the
Apple logo character, as shown in Figure 7–12.
Figure 7–12. The dialog box displaying MacRoman text with ASCII character 240
If your primary encoding is a different single-byte character set, then you may get a
different symbol instead. As for multibyte character sets such as MacJapanese, they
don’t work at all well with ASCII number and ASCII character, which are only designed
to handle single bytes—another reason why the changes to text handling in AppleScript
2.0 are so welcome.
NOTE: The ASCII number and ASCII character commands still exist in the Standard
Additions scripting addition in Leopard and later, but their use should be avoided unless your
scripts need to run on Tiger or earlier. Instead, use the text class’s id property and the
character id specifier to convert AppleScript strings to their corresponding code points and
back. This will ensure you get the correct results, no matter what your text might be.
Example Projects
Let’s put your new knowledge of AppleScript text to good use in a couple of projects.
The first project is a fairly simple but useful one: defining a new command that will find
and replace text in AppleScript. This is a common task, so you will no doubt find this
code useful in your own scripts as well.
The second project involves extracting meeting information from an e-mail message in
Mail and creating a new iCal entry for it. This task is a bit more specialized, but it
demonstrates nicely how AppleScript code can work together with scriptable
applications to carry out sophisticated tasks.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
202
CHAPTER 7: Working with Text
Defining a Find-and-Replace Command
Performing find and replace operations with text item delimiters is such a common task
that it’s worth defining our own find_and_replace command just for this purpose. To do
this, we will create a user-defined handler named find_and_replace that we can add to
any script that needs it. Although we won’t cover handlers properly until later in the
book, it won’t do any harm to dabble in them a little now.
Let’s start by planning the find_and_replace command itself. We’ve already picked a
name for it, so the next step is to decide what parameters it needs.
Just like application commands, user-defined commands can accept any number of
objects as parameters. Those objects are then passed into the handler, which can use
them however it likes. The principle is the same in both cases, although the syntax for
user-defined commands is a bit different.
Anyway, to find and replace a substring within a larger string, the find_and_replace
command needs to supply three string objects to the handler: the string to be modified,
the substring to search for, and the string that will be inserted in its place. Once the
handler is done, it will return a new, modified string as its result.
Once we know what parameters the handler can take, we can begin writing it. A userdefined handler statement consists of an opening line, a closing line, and any number of
statements in between. The first line must begin with the keyword on, followed by the
handler name, in this case find_and_replace. After the handler name comes a pair of
parentheses containing the names of the variable to which each of our three parameter
strings will be assigned. Let’s call these the_text, search_text, and replacement_text.
The last line of the handler consists simply of the keyword end, followed by the name of
the handler again.
Here is how the handler looks so far:
on find_and_replace(the_text, search_text, replacement_text)
-- Find-and-replace code goes here...
end find_and_replace
Next, we’ll fill in the lines of code that will perform the actual find-and-replace work.
Take another look at lines 2 to 7 of Script 7–9 to remind yourself how it did this part:
2.
3.
4.
5.
6.
7.
set text item delimiters to "[company]"
set temporary_list to text items of form_text
set text item delimiters to "Disney Inc."
set finished_form to temporary_list as text
set text item delimiters to ""
return finished_form
Line 2 sets AppleScript’s text item delimiters to the string to be found, and then line 3
breaks up the original string according to this delimiter and stores the resulting list in a
temporary variable. Line 4 sets the text item delimiters to the text to insert into the gaps,
and line 5 coerces the temporary list back into a string. Line 6 resets the text item
delimiters to their default value; although you don’t have to do this, some AppleScripters
consider it good manners to do so. Line 7 returns the finished result.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
203
The only changes we have to make to this code are to replace the hard-coded delimiter
strings with the search_text and replacement_text variables and rename the other
variables to something a bit more generic (the_text and finished_text).
Because this handler may be used in a variety of situations, we’ll also improve the way
that it manages the text item delimiters property. Instead of simply setting the
property to an empty string, we will preserve its current value at the start of the handler
and restore it at the end. That way, a script can set the text item delimiters property
to a particular value, send some find_and_replace commands, and then safely perform
some other tasks using the delimiters it set earlier.
Let’s put it all together. Here is the assembled handler after these tweaks have been
made:
Licensed by
Jim Kilcullen
2884260
on find_and_replace(the_text, search_text, replacement_text)
set old_delims to text item delimiters
set text item delimiters to search_text
set temporary_list to text items of the_text
set text item delimiters to replacement_text
set finished_text to temporary_list as text
set text item delimiters to old_delims
return finished_text
end find_and_replace
Now, whenever you want to perform a find-and-replace job on an AppleScript string, all
you need to do is add this handler to your script. For example, Script 7–10 shows the
result of rewriting Script 7–9 to use the new find_and_replace handler.
Script 7–10.
set form_text to "Let it be known that [company] is responsible for any damage" ¬
& " any employee causes during [company]'s activity while in the conference."
set finished_form to find_and_replace(form_text, "[company]", "Disney Inc.")
on find_and_replace(the_text, search_text, replacement_text)
set old_delims to text item delimiters
set text item delimiters to search_text
set temporary_list to text items of the_text
set text item delimiters to replacement_text
set finished_text to temporary_list as text
set text item delimiters to old_delims
return finished_text
end find_and_replace
Run it, and the result should be exactly the same as before.
Now, you might be wondering what the point was of reworking this particular script to
use a handler—after all, it hasn’t made it any shorter or simpler. True; but now that
you’ve written the handler once, you can quickly add it to any script that needs it,
instead of rewriting the find-and-replace code from scratch.
There are also times when you need to find and replace text in several different areas of
a script. Without a handler, you would need to copy and paste the find-and-replace
code multiple times, making your code larger and more complicated than necessary.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
204
CHAPTER 7: Working with Text
You can avoid this situation by adding a single find_and_replace handler and using
multiple find_and_replace commands instead.
TIP: If you want to consider case or ignore diacritical marks when finding and replacing text,
just wrap your individual find_and_replace commands in the appropriate
considering/ignoring blocks and AppleScript will automatically apply those attributes to the
code in your find_and_replace handler.
Transferring Meeting Arrangements from Mail to iCal
From my experience, looking at the words and paragraphs components of strings can
be extremely useful. Either breaking down a text file into paragraphs and looping
through them or referencing the paragraphs of a string one by one is essential, and
asking for every word of some text is great for finding the information you need.
As an exercise, let’s create a script that will parse some text and use the information.
The script is one I actually use myself for scheduling purposes. One of my large clients
has scheduling software that sends e-mails to me whenever I’m scheduled to be part of
a meeting. The e-mails are well formatted, and their content is completely predictable
and reliable, because a computer generates them. The e-mail contains, in plain text,
information about the location and time of the meeting and some other general
information. The goal of the script you are going to create is to convert these e-mails
into events in your iCal calendar.
We will start by creating the script as a single flow, from top to bottom. The first part will
gather the text from the message in Apple’s Mail application. Then, we will extract the
actual meeting information from that text, and we will end by adding a new event to iCal
with the information we’ve collected.
NOTE: When designing a script for other people to use, you should make the script as reliable
and safe to use as you can; for example, by checking that the user selected a suitable message
in Mail before processing it, and halting the script with a helpful explanation: “Please make sure
an e-mail message containing meeting arrangements is selected in Mail’s message viewer
window, and run this script again.” This sort of user-friendly error handling takes time to design
and develop, and makes scripts larger and more complex, but it ensures that different errors are
reported to the user in a way they can understand and deal with. For now, we’ll leave out any
special error checking or reporting code in order to keep the project as simple as possible, but
once you’ve learned how to deal with errors in Chapter 15, you can always add your own
improvements.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
205
Getting the Message from Mail
The script will start by extracting the raw information from Mail. We will assume that
there’s a message selected and that it contains text formatted to our expectations.
Like many applications, Mail provides a selection property that identifies the current
graphical user interface (GUI) selection. The selection property belongs to the
application object and therefore can be accessed from within the initial application
tell block.
In Mail, like some other applications, the selection property contains a list that can
include any number of items or no items at all; in this case, it holds only a single item,
and we need to retrieve it to get its text.
Before you start writing here, make sure the Mail application is running. Type the content
of the message from the following text into a new outgoing e-mail and send it to your
own e-mail address:
Meeting Reminder
Subject: Preapproval of the meeting proposed in the initial proposal draft
When: Friday, October 2, 2009, 8:30 AM to 9:30 AM (GMT–05:00) Eastern Time
Where: Break Room in the Marketing Wing
Next, pick up your new mail, and make sure this message is selected in the inbox of
Mail’s message viewer window. This message will serve as your test data as you write
and test this script.
I realize you might not be using Mail, or that you might prefer to ignore this task while
developing and testing the rest of the script. If so, you can insert the following code
instead:
set message_text to "Meeting Reminder
Subject: Preapproval of the meeting proposed in the initial proposal draft
When: Friday, October 2, 2009, 8:30 AM to 9:30 AM (GMT-05:00) Eastern Time
Where: Break Room in the Marketing Wing"
This will create the dummy text within AppleScript itself and assign it to the variable
named message_text. This way you can bypass Mail and get right to cleaning the text in
the next section.
All this, by the way, isn’t just logistics that relate strictly to learning AppleScript from this
book; these are different tasks you should perform while writing actual scripts, including
creating dummy data, creating objects in an application to use in testing, and so on.
Assuming you are a fan of Mail, let’s begin by looking at how we can extract the
message content. For this exercise, we’ll assume the user will select the e-mail message
they want and then run the script manually. There are other approaches we could use—
for example, using a Mail rule to run the script automatically whenever a new e-mail
arrives—but this way is simplest to understand and also an ideal first step because it’s
quick and easy to test out.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
206
CHAPTER 7: Working with Text
To get a list of the currently selected e-mail messages, we use the selection property of
Mail’s application object. Figure 7–13 shows that the selection property is defined as
part of the application class’s definition in the Mail suite.
Figure 7–13. Part of the Mail application’s dictionary, showing the selection property of the main
application class
Write the following lines, and run the script:
tell application "Mail"
get selection
end tell
Assuming you have selected only the test e-mail that you just sent to yourself, the result
is a list containing a single reference to the selected message object. Here is a typical
example of this:
--> {message id 70854 of mailbox "INBOX" of account "your.name@example.org"
of application "Mail"}
Since we want only the first reference and not the entire list, let’s change the script to
get the first item of the list:
tell application "Mail"
get item 1 of (get selection)
end tell
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
207
NOTE: Notice that we’re using item 1 of (get selection) here instead of item 1 of
selection. That’s because we have to get the entire list out of Mail first and then use
AppleScript to extract the item we want.
Now that we have a reference to the message we’re interested in, let’s go all the way
and extract the text. In Mail, every message object has a content property that includes
the body text of the message. You can see this in Mail’s dictionary if you look at the
message class definition in the Message suite, as shown in Figure 7–14.
Figure 7–14. Part of the Mail application’s dictionary, showing the content property defined by the message class
What we need is to get the value of the selected message’s content property into a
variable. Here is how:
tell application "Mail"
set the_message to item 1 of (get selection)
set message_text to content of the_message
end tell
Run this script, and the result should be a string that looks like this:
--> "Meeting Reminder
Subject: Preapproval of the meeting proposed in the initial proposal draft
When: Friday, October 2, 2009, 8:30 AM to 9:30 AM (GMT-05:00) Eastern Time
Where: Break Room in the Marketing Wing"
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
208
CHAPTER 7: Working with Text
Notice that the message text has four paragraphs and that the information we want is
concentrated in paragraphs 2, 3, and 4.
Parsing the Message Text
Now that we’ve retrieved the raw message text, the next step is to break it down and
extract the bits we want.
Let’s add the lines of code that assign the contents of these paragraphs to different
variables. We will make the identifiers of these variables as descriptive as you can:
set message_subject_line to paragraph 2 of message_text
set message_dates_line to paragraph 3 of message_text
set message_location_line to paragraph 4 of message_text
Now we can start to turn the text into the information we need. If you examine iCal’s
dictionary, you can see that it includes an event class. That is the class of the object we
need to create. Figure 7–15 shows the definition for iCal’s event class in AppleScript
Editor’s dictionary viewer.
Figure 7–15. Viewing the definition of iCal’s event class in AppleScript Editor
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
209
As you can see, an event object has over a dozen properties (including the ones defined
by the parent item class), out of which five are of interest to us: start date, end date,
summary, location, and status.
Of these four properties, start date and end date need an object of class date, summary
takes a string, and the status property takes one of the following iCal-defined
constants: none, cancelled, tentative, or confirmed.
Anyway, the next job is to create four variables that hold objects ready to go into the first
four of these properties. We’ll call these variables start_date, end_date, the_summary,
and the_location. For the status property, we will just insert the confirmed value
directly.
The next portion of the script will mold the plain text we got from the message into data
that will fit into these variables. Let’s start with a couple of easy ones: summary and
location. These are both just text descriptions, and the text in the
message_subject_line and message_location_line variables is almost perfect as it is.
The only thing we’ll do to improve them is remove the label at the start of each line.
Since we know that each label always consists of a single word, we will ask AppleScript
for the text range beginning at the second word and ending at the end of the string. Add
the following line:
set the_summary to text (word 2) thru -1 of message_subject_line
Run the script to make sure it works. The result is as follows:
--> "Preapproval of the meeting proposed in the initial proposal draft"
Now do the same for the message location line and test that as well:
set the_location to text (word 2) thru -1 of message_location_line
--> "Break Room in the Marketing Wing"
Next, we need to attend to the dates. Let’s start by breaking down the
message_dates_line variable into words. Because this task is a bit more complex, you
might find it helps to work in a separate, temporary document in AppleScript Editor until
you have a solution, so create a new document and then type the following code to
assign a dummy value to a message_dates_line variable there:
set message_dates_line to ¬
"When: Friday, October 2, 2009, 8:30 AM to 9:30 AM (GMT–05:00) Eastern Time"
The first task is to figure out exactly how to break this text down to get the words we
need, so type the following:
words of message_dates_line
Run the script, copy the result, and paste it in any text editor or into a blank script
window. We will use that text as a reference, allowing us to see what the different words
are and their order.
The result should be a list with 17 items:
--> {"When", "Friday", "October", "2", "2009", "8", "30", "AM", "to",
"9", "30", "AM", "GMT", "05", "00", "Eastern", "Time"}
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
210
CHAPTER 7: Working with Text
A quick analysis reveals that items 3, 4, and 5 contain the date; items 6, 7, and 8 make
up the start time; and items 10, 11, and 12 make up the end time.
In AppleScript, a date object contains both a date and a time. In fact, if we don’t specify
a time, AppleScript assigns midnight of that date as the time.
In this case, we will create two strings: one will have the date and the start time, and the
other will have the same date and the end time. We will then convert these strings into
date objects so that they can be used by iCal.
First, though, we need to assemble the strings. Here is one way we can do it:
set the_meeting_date to ¬
word 3 of message_dates_line & space & ¬
word 4 of message_dates_line & ", " & ¬
word 5 of message_dates_line
set the_start_time to ¬
word 6 of message_dates_line & ":" & ¬
word 7 of message_dates_line & space & ¬
word 8 of message_dates_line
set the_end_time to ¬
word 10 of message_dates_line & ":" & ¬
word 11 of message_dates_line & space & ¬
word 12 of message_dates_line
Let’s examine these variables. Add the following line:
return the_meeting_date
What you will get is a string containing the date only, "March 2, 2001". You can do the
same with the other variables to examine their values for accuracy.
Although this approach will do the job, another, more elegant solution is to use some
more fancy text range references to get the substrings we want directly:
set the_meeting_date to text (word 3) thru (word 5) of message_dates_line
set the_start_time to text (word 6) thru (word 8) of message_dates_line
set the_end_time to text (word 10) thru (word 12) of message_dates_line
You can probably guess which technique I like most—if only because it saves me a
bunch of typing!
The next two lines concatenate the date string and each of the strings containing the
start time and end time and convert them into date objects:
set start_date to date (the_meeting_date & space & the_start_time)
set end_date to date (the_meeting_date & space & the_end_time)
Run the script to see how AppleScript has converted each date-time string into a date
object. As long as you give AppleScript some sort of a date containing at least the
month, day, and year, it’ll take it from there and make it into a date it can understand.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
211
NOTE: The way in which AppleScript converts date strings to date objects depends on your
system settings. This example assumes you’re using US-style dates or similar. If your settings
are different and the script reports an error when creating date objects, go to the Formats tab of
the Language & Text panel in System Preferences and temporarily change the region to United
States while testing this script. I’ll discuss these issues in further detail in Chapter 9, and also
look at an alternative way to create date objects that will always work, regardless of a user’s
date and time preferences.
Once you are happy with your date parsing code, copy those lines into the main script.
Now that the text parsing code is complete, it’s time to begin the final stage.
Creating the Event in iCal
At this point, we have all the information that our script needs neatly formatted into
dates, text, and so on. Now let’s create the event in iCal.
iCal’s object model starts with the application object, which contains calendar elements,
each of which can contain event elements. To create a new event object, we must first
identify an existing calendar object that will contain this event. Since a working iCal
application must have at least one calendar element, we can safely talk to calendar 1.
Here is the tell block we will use to talk to iCal:
tell application "iCal"
-- Commands go here...
end tell
I always complete the tell blocks first before inserting the command. This is a way to
eliminate nagging little typos that will steal more debugging time than they deserve.
Now, type the following line in the tell block:
make new event at end of calendar 1 with properties ¬
{start date:start_date, end date:end_date, ¬
summary:the_summary, location:the_location, status:confirmed}
This statement starts with the make command. The new parameter is event, which is the
class of the object we’re creating. The at parameter indicates where the new event
object should appear, in this case at the end of calendar 1’s existing event elements.
iCal is smart enough to work out that end of calendar 1 really means end of elements
of calendar 1, which saves some extra typing. Also, as part of the make command, we
can specify initial values for some or all of the new object’s properties. This is a fast and
efficient way to set the start date, end date, and so on.
Script 7–11 shows the finished script.
Script 7–11.
-- Get the message text from Mail
tell application "Mail"
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
212
CHAPTER 7: Working with Text
set the_message to item 1 of (get selection)
set message_text to content of the_message
end tell
-- Parse the message text
set message_subject_line to paragraph 2 of message_text
set message_dates_line to paragraph 3 of message_text
set message_location_line to paragraph 4 of message_text
set the_summary to text (word 2) thru -1 of message_subject_line
set the_location to text (word 2) thru -1 of message_location_line
set the_meeting_date to text (word 3) thru (word 5) of message_dates_line
set the_start_time to text (word 6) thru (word 8) of message_dates_line
set the_end_time to text (word 10) thru (word 12) of message_dates_line
set start_date to date (the_meeting_date & space & the_start_time)
set end_date to date (the_meeting_date & space & the_end_time)
-- Create the iCal event
tell application "iCal"
make new event at end of calendar 1 with properties ¬
{start date:start_date, end date:end_date, ¬
summary:the_summary, location:the_location, status:confirmed}
end tell
Make sure that you’ve deleted or commented out any temporary test code, check that
your test mail message is still selected in Mail, and run the script to find out if it works! If
all goes well, a new event should appear in iCal, as shown in Figure 7–16.
Figure 7–16. The iCal event created using the information from the Mail message
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 7: Working with Text
213
Summary
Whew! As you can see, text in AppleScript is a pretty big subject, so let’s take a moment
to review what you’ve learned before we move on to the next topic.
We started with a quick crash course on how computers deal with text in general. You
learned that computer hardware doesn’t understand human-readable text, only
numbers, so the operating system and applications rely on character sets to map
different characters (glyphs) to numbers (code points) that computers can understand.
You were introduced to some of the character sets that have been used over the years,
including ASCII, MacRoman, and Unicode. You learned about the shortcomings of the
older character sets and why the modern replacement to them, Unicode, is a good thing
in general.
Licensed by
Jim Kilcullen
2884260
Fortunately, you won’t have to worry about character set issues too much when
working in AppleScript because from Mac OS X 10.5 onward the entire language is
based on Unicode and nothing else. You will have to deal with them when you start
reading and writing text files directly in AppleScript, but we’ll cover those issues later
on in Chapter 17.
Having gotten all the boring background and jargon out of the way, we next looked at
the various properties and elements that AppleScript’s text class defines for extracting
information from AppleScript text objects (or strings, as most scripters like to call them).
You learned how to extract individual characters, words, and paragraphs from strings,
and how to retrieve a substring by referring to the original string’s text elements.
Next we covered the various operators you can use to concatenate, compare, and
coerce strings, followed by the standard commands, count and offset, that you can use
to measure strings and search them.
In the “Working with Text Item Delimiters” section, we looked at the coolest stringrelated feature of all: text item delimiters. You discovered how to pull a piece of text
apart using the text item delimiters property and the string’s text item elements, and
how to put it together again using a list-to-text coercion. We looked briefly at how to use
these techniques to find a particular phrase in a piece of text and replace it with another.
Finally, following a quick reference section to help you understand how text works
differently in pre-Leopard versions of AppleScript (useful if you need to write, maintain,
or update Panther- or Tiger-based scripts), we developed a couple of practical projects
that involve text manipulation.
The first project created a custom find_and_replace handler that your own scripts can
use to find and replace text in any string, simply by sending a find_and_replace
command to themselves.
The second project produced a complete script that can extract information from a preformatted e-mail message in Mail and then parse out the important details and put them
into iCal as a new event. Integrating desktop applications in this way is the biggest
reason for learning and using AppleScript in the first place. As you can see, it is possible
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
214
CHAPTER 7: Working with Text
to achieve some impressive results with just a little bit of AppleScript “glue” code and
some powerful scriptable applications at your disposal.
Now that you’ve got your head around AppleScript strings, it’s time to move on to the
next class (or classes) of objects you’ll use in AppleScript: numbers.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
215
Chapter
8
Working with Numbers
No matter what you do in AppleScript, numbers and math are everywhere—page layout
automation, database interaction, and system administration; all require some kind of
number manipulation. Some of my graphic-intensive scripts even forced me to pick up a
trigonometry book and figure out triangles, sines, and cosines! Throughout the book,
you will be attacking number problems and using the concepts covered in this chapter.
Introducing Integers and Reals
AppleScript supports two classes of numbers: integer and real. An integer is a whole
number without a decimal fraction and with no potential of ever getting one. Integers
can, however, be negative numbers. Real numbers, on the other hand, have decimal
points, even if the decimal point is ceremonial, like in the case of the real 1.0. It’s equal
in value to the integer 1, but it is a real nonetheless.
When you do math, some operations return reals and some return integers. This
generally isn’t an issue because reals and integers can be used pretty much
interchangeably in AppleScript. You can always use an integer in any situation where a
real number is expected, and you can usually use a real number in place of an integer
(though if it has a fractional part, AppleScript may round it to the nearest whole number
for you).
Here are some examples of integers,
0
3
-712
536870911
and some examples of reals:
3.0
-0.017
8591.2
4.51E+19
1.577E-10
215
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
216
CHAPTER 8: Working with Numbers
You can find out the exact class of a number by getting the value of its class property:
class of 2003
--> integer
class of 1.5
--> real
Real numbers have the tendency to be written using exponential notation, which is the
scientific form of a number used to shrink the length of a number while (for the most
part) not changing its value. You can write large numbers in AppleScript in their long
form (say, 120,000,000), but as soon as the script is compiled, these long numbers get
converted to their exponential forms, which can prove irritating.
For example, try to write the following in a new AppleScript Editor window:
10000.0
When you compile the script, the number will change to this:
1.0E+4
In mathematical terms, the number breaks down into the coefficient, which is always a
number from 1.0 up to, but not including, 10.0, and the exponent, which is the number
appearing after the E, in this case +4.
NOTE: Using traditional scientific notation, 10,000 would be written as 1.0 × 104. However, you
can’t use true multiplication signs or superscript text in AppleScript code, so an equivalent “E
notation” is used instead.
In other words, AppleScript tells you, “I moved the decimal point four spots to the left.”
Move the decimal point back, and you have your 10,000 back.
It’s simple, really! If you take the number 12345678.7654321 and compile it in a script
window, it will be displayed as 1.23456787654321E+7. All you have to do is shift the
decimal point seven spaces to the right to get the number 12345678.7654321.
The same decimal-shifting idea works with negative exponential numbers. That doesn’t
mean the number itself is negative, just that the direction of the decimal point is. For
example, 1.0E-4 is actually 0.0001. Notice the decimal point moved four spots to the
right. Move the decimal, and you get the number.
TIP: AppleScript automatically displays any real number that is less than 0.0001 or greater than
10,000 using E notation; otherwise, the number is displayed as is.
Operators and Commands
AppleScript provides a number of math operators for performing simple arithmetic
operations, while its comparison operators, which you used in the previous chapter to
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 8: Working with Numbers
217
compare text, are equally adept at performing numerical comparisons. The Standard
Additions scripting addition defines two math-related commands, round and random
number. The following sections will look at how each of these operators and commands
can be put to good use when working with numbers.
Math Operations
Although you can use numbers in many ways that require no more than some counting
skills, when you think numbers, you probably think math. I personally love math and look
forward to solving any challenging operations a script may require.
The operators you can use with numbers are the familiar ones such as addition,
subtraction, division, and so on, and some less often used ones such as div and mod.
Table 8–1 lists and describes the operators you can use with numbers.
Table 8–1. Math Operators
Operator
Name
Description
+
Addition
Adds the left and right numbers.
-
Negation (with one operand)
Converts the single number to its right from positive to
negative or from negative to positive.
-
Subtraction(with two operands) Subtracts the right number from the left number.
*
Multiplication
Multiplies the left and right numbers.
/
Division
Divides the left number by the right number.
div
Integral division
Returns the number of times the right number fits
whole in the left number.
mod
Remainder (modulo)
Subtracts the right number from the left number
repeatedly until the remainder is less than the right
number and returns the final remainder.
^
Exponent
Raises the left number to the power of the right
number.
Adding, Subtracting, Multiplying, and Dividing Numbers
AppleScript’s four basic math operators—addition, subtraction, multiplication, and
division—work just as you would expect them to. Here are some examples:
5 + 3
--> 8
12 - 8.5
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
218
CHAPTER 8: Working with Numbers
--> 3.5
3 * 10
--> 30
10 / 4
--> 2.5
7.5 / 2
--> 3.75
Notice that integers and reals can be freely mixed together in calculations.
In the following script, I will show how to create a handler that takes a list of numbers
and returns a record with a few mathematical facts regarding the list. The resulting
record will include the list average, the highest number in the list, and the lowest number
in the list. If you fed the following list to the handler,
{10, 3, 5, 4, 13}
you’d get the following record as the result:
{average:7.0, high:13, low:3}
Here is the complete script:
1. math_facts({10, 3, 5, 4, 13})
2. on math_facts(numbers_list)
3.
set high_number to item 1 of numbers_list
4.
set low_number to item 1 of numbers_list
5.
set numbers_total to 0
6.
repeat with i from 1 to count numbers_list
7.
set the_number to item i of numbers_list
8.
if the_number > high_number then set high_number to the_number
9.
if the_number < low_number then set low_number to the_number
10.
set numbers_total to numbers_total + the_number
11.
end repeat
12.
set the_average to (numbers_total / (count numbers_list))
13.
return {average:the_average, high:high_number, low:low_number}
14. end math_facts
I started by creating three variables, on lines 2, 3, and 4. These variables, for the most
part, will hold the values that will return the handler’s result. The variables are
high_number, low_number, and numbers_total, which will be used to get the list average
at the end.
The repeat loop between lines 6 and 11 is the main loop that goes through the numbers
in the list and analyzes each number to see whether it fits in the high number or low
number spots and to add it to the numbers total.
Line 8 determines whether the currently processed number is larger than the value
stored in the high_number variable. If it is, that number will become the new value of the
high_number variable. This way, when the repeat loop concludes, the high_number
variable will contain the highest number from the number_list variable. Line 9 is
responsible for determining the lowest number in a similar fashion.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 8: Working with Numbers
219
Line 12 calculates the average of all the numbers by dividing their total, stored in the
variable numbers_total, by the number of items in the list.
Line 13 puts all this information into a neatly labeled record and returns it.
Negating Numbers
To convert a number from positive to negative, or vice versa, simply add the minus sign
before it, even if the number is in a variable:
set n to 500
set reverse_n to -n
--> -500
In this situation, the minus operator is the unary negation operator, not the binary
subtraction operator that allows you to subtract one number from the other. (Unary
means an operator has only one operand; binary means an operator has two of them.)
The following user-defined handler uses the negation operator to calculate the absolute
value of a given number:
on abs_num(n)
if n < 0 then set n to -n
return n
end abs_num
Let’s say you need to calculate the difference between two distances. The subtraction
operation may return a positive or negative number depending on which operand is
larger; however, the final result should always be a positive number. How can we ensure
this? The solution is simple: just add the abs_num handler to the script and, once the
subtraction is performed, use an abs_num command to get the absolute value of the
result:
set d1 to 23
set d2 to 45.5
abs_num(d1 - d2)
--> 22.5
Calculating the Integral and Remainder
Now let’s look at the mod and div operators. Although mod and div are used less often
than other math operators, when you need them, they really shine.
mod and div deal with how many instances of a number can fit inside a different number
without breaking. For instance, div can tell you that 2 can fit three times in 7.5, while mod
will tell you that after you fit 2 in 7.5 three times, the remainder is 1.5:
7.5 div 2
--> 3
7.5 mod 2
--> 1.5
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
220
CHAPTER 8: Working with Numbers
Why is this so great? Well, I’ll discuss a couple of uses of div and mod. First, what if you
want to take a large number of seconds and show it as minutes and seconds? You can
do something like this:
set
set
set
set
-->
total_seconds to 735
the_minutes to total_seconds div 60
extra_seconds to total_seconds mod 60
the_time to (the_minutes as text) & ":" & extra_seconds
"12:15"
Second—say you are printing postcards—what if you need to fit four postcards per
page, and the number of postcards changes from job to job? If a job has 27 postcards,
how many whole pages will you need? You need the following calculation:
set total_postcards to 27
set postcards_per_page to 4
set whole_pages to total_postcards div postcards_per_page
if whole_pages mod postcards_per_page ≠ 0 then
set whole_pages to whole_pages + 1
end if
return whole_pages
--> 7
27 div 4 returns 6, because 4 fits 6 times into 27, so we know we will completely fill six
pages. We then use the mod operator to check whether we need a partially filled page at
the end. If the remainder is 0, it means that the division is perfect—for example, 24
postcards would fit exactly onto 6 pages. But if the remainder is not 0, then you need to
add a page for the remaining postcards.
You can also use the mod operator to check whether a number is whole or not:
on is_whole_number(n)
return n mod 1 = 0
end is_whole_number
n mod 1 calculates the fractional part of the number; for example, 2.0 mod 1 returns 0.0,
while 3.3 mod 1 returns 0.3. We then check whether this value is 0—if it is, we know the
original number was whole, and if it isn’t, we know it must have had a fractional part:
is_whole_number(2.0)
--> true
is_whole_number(3.3)
--> false
Using the Exponent Operator
The final math operator we’ll look at is the exponent (^) operator, which raises the left
operand to the power of the right operand. For example, to calculate the cube of 2, use
the following:
2 ^ 3
--> 8.0
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 8: Working with Numbers
221
To calculate the square root of 9, use the following:
9 ^ 0.5
--> 3
The following example combines the exponent operator to calculate the distance
between two points—with a little help from Greek mathematician Pythagoras:
on distance_between_two_points(x1, y1, x2, y2)
set dx to x1 - x2
set dy to y1 - y2
return ((dx ^ 2) + (dy ^ 2)) ^ 0.5
end distance_between_two_points
The distance_between_two_points handler takes four parameters representing the X and
Y coordinates of each point. The next two lines work out the horizontal and vertical
distances, which represent the lengths of the two short sides of a right-angled triangle.
The last line employs the Pythagorean theorem (a2 + b2 = c2, or The square of the
hypotenuse of a right triangle is equal to the sum of the squares on the other two sides)
to calculate the length of the longest edge of the triangle, or the distance between the
two points.
For example, given the points (1, –2) and (4, 2), we can calculate the distance between
these two points as follows:
distance_between_two_points(1, -2, 4, 2)
--> 5.0
Comparison Operations
You also have the comparison operators, which return a Boolean object (that is, true or
false). Table 8–2 describes the comparison operations you can use with numbers.
Table 8–2. Comparison Operators
Operator Name
Description
=
Is equal to
Returns true if both operands are the same.
≠
Is not equal to
Returns true if the operands are different.
<
Is less than
Returns true if the left operand is less than the right
operand.
≤
Is less than or equal to
Returns true if the left operand is less than or equal to the
right operand.
>
Is greater than
Returns true if the left operand is greater than the right
operand.
≥
Is greater than or equal to
Returns true if the left operand is greater than or equal to
the right operand.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
222
CHAPTER 8: Working with Numbers
TIP: On a US-style keyboard, type Option-equal (=) to insert the ≠ symbol, Option-comma (,) to
insert ≤, and Option-period (.) to insert ≥. Or you can use plain English equivalents if you prefer:
is not equal to, is less than or equal to, and is greater than or equal
to—see Chapter 13 for more information on operator synonyms.
Here are some examples:
3 = 6
--> false
7.0 = 7
--> true
3.7 ≠ -5
--> true
0.5 > -39
--> true
14 ≥ 14
--> true
-2 < -5
--> false
0.7 ≤ 0.5
--> false
CAUTION: If you are used to working in other scripting languages, take care. Most languages
use = to assign values to variables, == to compare for equality, and != to compare for inequality.
In AppleScript, using == and != will prevent the script from compiling, while the = symbol
performs a comparison, not an assignment.
Comparing Reals Can Be Trickier Than You Think
So far, working with numbers seems straightforward—and it is…usually. Unfortunately,
there is one caveat, which has to do with the way that computer hardware represents
real numbers.
Consider the following code:
0.7 * 0.7
Run it, and AppleScript Editor displays exactly the result you’d expect: 0.49. Now run
the following:
0.7 * 0.7 = 0.49
The result should be true, right? Well, try it and see:
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 8: Working with Numbers
223
0.7 * 0.7 = 0.49
--> false
Yikes, that makes no sense at all! Aren’t computers meant to be precise and
predictable? Well, they are predictable (when you know what to expect), but being 100
percent precise can be surprisingly difficult for some tasks. The problem is that the
computer hardware uses a limited number of bits to represent real (“floating-point”)
numbers: 64 bits to be exact. Some real numbers can be perfectly represented in 64 bits
or less, but others are only an approximation—close enough for most purposes, but not
absolutely accurate.
Because the limited precision of real numbers is due to the limitations of the underlying
hardware, it is something that all programmers have to live with, regardless of the
language they’re using.
Licensed by
Jim Kilcullen
2884260
CAUTION: Just to add to the confusion, the tiny rounding errors that exist in some real numbers
aren’t always visible within AppleScript. For example, 0.49 is really 0.4899999999999, but
appears as 0.49 in source code and script results. So everything looks okay on the surface, but it
could give you an unwanted surprise if you aren’t aware of what’s going on underneath.
For most tasks involving real numbers, the slight loss of precision isn’t a practical
problem—the results are “good enough.” In situations where absolute precision is really
needed—most often when comparing one real number against another—you just have
to allow a certain amount of leeway. For example, rather than using a simple equality
test, a safer solution is to check that the number you’re testing is within a certain range,
like this:
set error_margin to 1.0E-10
set the_number to 0.7 * 0.7
the_number > (0.49 - error_margin) and the_number < (0.49 + error_margin)
--> true
As long the lower limit of the range is fractionally less than the number you want and the
upper limit is marginally above the number you want, this will compensate for any
imprecision that might exist in the numbers used.
Performing Multiple Comparisons
Comparison operators can be quite boring when used one at a time. However, when
you gang them up, you can create some mighty powerful, and also rather confusing,
expressions.
A simple expression may look like this:
the_age ≥ 18
This evaluates whether the value of the variable the_age is equal to or greater than 18.
This expression will return true or false. You can combine this simple expression with
other simple expressions to carry out a complex task. Suppose you need to write a
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
224
CHAPTER 8: Working with Numbers
statement that will approve or reject a credit card application. You’d need to check for a
number of true-or-false conditions such as age, household income, bankruptcies, credit
ratings, current debts, and so on.
You can use AppleScript’s three Boolean logic operators—and, or, not—to combine two
or more simple comparison expressions into a powerful compound expression.
For example, Script 8–1 includes a compound expression that uses multiple comparison
operations and no less than nine logical operators to connect everything.
Script 8–1.
set is_applicant_approved to ¬
age ≥ 18 and ¬
((bankruptcies = 0 and credit_rating > 700 and debt < 20000) ¬
or (bankruptcies = 0 and credit_rating > 500 and debt < 10000)) ¬
or (bankruptcies = 0 and debt > 1000 and will_give_up_first_born)
Introducing Operator Precedence
When several operations are combined to create a more complex expression,
AppleScript follows a strict set of rules, known as operator precedence rules, to decide
the exact order in which operations should be performed.
Chapter 13 will explain AppleScript’s precedence rules in full, but while we’re on the
subject of math-related operations, let’s take a quick look at how the precedence rules
for math operators work. Fortunately, the precedence rules for AppleScript’s math
operators are much the same as the rules you learned in high school math class, so you
should find them fairly easy to remember.
First up, we have the negation (unary minus) operator, -. This has the highest
precedence of all math operators, so a negation operator in front of a positive number
always gives you a negative number.
Next, we have the exponent operator, ^. Since the negation operator has higher
precedence, if you write an expression like this,
-2 ^ -2
AppleScript will evaluate each of the negation operators first, giving us –2 and –2. It then
uses these two values as operands to the exponent operator, to produce the final result
(0.25).
Following the exponent operator, we have several operators all with equal precedence:
multiplication (*), division (/), integral division (div), and remainder (mod). And beneath
these we have the addition (+) and subtraction (binary minus, -) operators, which also
have the same level of precedence as each other. This means that if you write an
expression like this,
3 + 2 * 6 - 4 / 8
the multiplication and division operations will be evaluated first, since they have the
highest precedence in this case. This gives us the following intermediate result:
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 8: Working with Numbers
225
3 + 12 - 0.5
The addition and subtraction operations have equal precedence, so they are simply
evaluated from left to right to give us the final result:
14.5
Other operators, such as comparison and Boolean logic operators, have lower
precedence still, so in a large, complex expression that contains a mixture of math,
comparison, and logic operations, the math operations will normally be performed first,
then the comparison operations, and finally the logic operations.
Sometimes the default evaluation order is the one you want, in which case you don’t
need to do anything more to your code. However, often you’ll want AppleScript to follow
a different order. By grouping parts of a larger expression within parentheses, ( and ),
you can force AppleScript to resolve the smaller expression within the parentheses
before evaluating the larger expression around it. For example, given the following
complex expression,
(3 + 2) * (6 - 4) / 8
the smaller expressions within parentheses are resolved first. At this point, the
calculation looks like this:
5 * 2 / 8
The remaining operations are then evaluated to produce the final result:
1.25
CAUTION: Take care to position your parentheses correctly, especially if they are deeply nested.
Poorly placed parentheses may prevent your script from compiling or cause it to error or produce
the wrong result when run.
The round Command
Rounding numbers is an important aspect of scripting and programming. Although the
round command rounds the number you provide as its direct parameter, you can
perform many tasks with the command if you make some modifications to it.
Let’s look at the round command in detail. To begin with, the round command takes a
direct parameter, which is a real number. The result returned by the round command is
an integer.
To test the basic function of the round command, start a new script window, type each
of the following lines, and run each line separately to get the result. I included the result
on separate lines here:
round 1.5
--> 2
round 2.2
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
226
CHAPTER 8: Working with Numbers
--> 2
round -6.4
--> -6
You can fine-tune the behavior of the round command by using its optional rounding
parameter. The rounding parameter has five possible values, all of which are constants:
up, down, toward zero, to nearest (the default option), and as taught in school. The
following sections explain how each option affects the round command’s behavior.
Rounding Up
As it sounds, rounding up always rounds to the next higher integer. Here are some
examples:
round 1.1 rounding up
--> 2
round 5.5 rounding up
--> 6
round -2.9 rounding up
--> -2
Rounding Down
The opposite of rounding up, rounding down always rounds to the next lower integer.
Here are some examples:
round 1.7 rounding down
--> 1
round 5.5 rounding down
--> 5
round -2.1 rounding down
--> -3
Rounding Toward Zero
rounding toward zero acts the same as rounding down with positive numbers, and with
negative numbers it acts like rounding up would. In other words, it simply “chops off”
the decimal portion of the number. Here are a few examples:
round 17.5 rounding toward zero
--> 17
round -2.5 rounding toward zero
--> -2
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 8: Working with Numbers
227
Rounding to Nearest
rounding to nearest is the default behavior that will be used if none other is specified. It
works as follows:
If the fractional part is less than .5, AppleScript rounds toward zero.
If the fractional part is greater than .5, AppleScript rounds away from
zero.
If the fractional part is .5 and the whole part is an odd number,
AppleScript rounds away from zero.
If the fractional part is .5 and the whole part is an even number,
AppleScript rounds toward zero.
These rules may sound a bit fussy, but they ensure that exactly half of all numbers round
upward and exactly half round downward. This bias-free technique of rounding numbers
prevents your results from becoming skewed over time due to cumulative errors. Here
are some examples:
round 5.5 rounding to nearest
--> 6
round 4.5 rounding to nearest
--> 4
Rounding As Taught in School
rounding as taught in school works almost the same as rounding to nearest, except
that numbers whose decimal part is .5 are always rounded away from zero. Here are
some examples:
round 5.5 rounding as taught in school
--> 6
round 4.5 rounding as taught in school
--> 5
round -2.5 rounding as taught in school
--> -3
TIP: As you can see, the round command only knows how to round to the nearest whole
number. Later in the chapter, we will define a new command, round_to_decimal_places,
for rounding to a specific number of decimal places.
The random number Command
What’s a programming language without the ability to generate random numbers?
“Incomplete” is the answer. Like other languages, AppleScript has a command for
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
228
CHAPTER 8: Working with Numbers
generating random numbers named, unsurprisingly, random number. You can provide the
random number command with a number of optional parameters to make it work for you
in many ways.
Random Number Result
The random number command returns a result that can be either an integer or a real,
depending on whether the parameters you provided are reals or integers.
Parameters
You can use the random number command as is, without any parameters. The result in
that case is a real number from 0 to 1, as shown in Figure 8–1.
Figure 8–1. The random number command used without parameters
The direct parameter you can use is a number, either a real or an integer, following the
command. Try this:
random number 5
The result is an integer from 0 to 5. Next, try this:
random number 5.0
Now the result is a real number with up to 12 decimal places, also from 0.0 to 5.0. You
can also use the range parameters from and to, like so,
random number from 20 to 30
or like so:
random number from 20.0 to 30.0
Note that if you provide a direct parameter as well as to/from parameters, only the direct
parameter is used. For instance, the following command generates an integer from 0 to
3, not a real from 20.0 to 30.0:
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 8: Working with Numbers
229
random number 3 from 20.0 to 30.0
The final parameter, with seed, is a bit obscure. It allows you to get the same sequence
of “random” numbers each time your script runs.
Okay, so isn’t asking for a nonrandom sequence of numbers contrary to the concept of
random numbers? Aren’t random numbers supposed to always be random? Well, yes,
but random number actually uses a pseudo-random number generator to produce its
results.
Truly random numbers are surprisingly hard to obtain on modern computers, which are
designed to be predictable and precise, for obvious reasons. A pseudo-random number
generator works around this limitation by obtaining an initial “seed” number calculated
from reasonably unpredictable operating system information such as the current date
and the times between user input. It then uses some clever math calculations to
generate a random-looking sequence of numbers from that seed.
Normally when you run a script that uses the random number command, you want the
random numbers to be different each time. Sometimes, however, it is useful to get the
same sequence of numbers each time—for example, when repeatedly testing a script. In
this case, you can reset the pseudo-random number generator by calling random number
once beforehand, giving it a with seed parameter of your choice.
For example, type the following script into AppleScript Editor and run it several times:
-- Seed the pseudo-random number generator
random number with seed 1
-- Now generate a non-random sequence of random numbers
set the_numbers to {}
repeat 10 times
set end of the_numbers to random number from 1 to 100
end repeat
the_numbers
--> {65, 48, 6, 15, 79, 27, 89, 78, 65, 50}
As you can see, it returns the same sequence of numbers each time. Try changing the
seed number to a different amount, and you will get a different, but still repeatable,
sequence.
Any time you want to get an unpredictable sequence of numbers, just disable or delete
the random number with seed... command, and random number will go back to using
the seed provided by the system.
Coercing to and from Numbers
AppleScript allows you to coerce integer values to several other classes of values:
boolean, real, text, and list. Real values can be coerced to integer, text, and list.
The following integer-to-Boolean coercions are supported:
0 as boolean
--> false
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
230
CHAPTER 8: Working with Numbers
1 as boolean
--> true
true and false can also be coerced back to 1 and 0 again. Trying to coerce other
integers to Booleans will give an error, however:
3 as boolean
--> Error: Can't make 3 into type boolean.
Integers can be coerced directly to reals, for example:
678 as real
--> 678.0
Reals can also be coerced to integers, but the process is a little more complex.
If the decimal portion is .0, the resulting integer is equal to the original real number:
-17.0 as integer
--> -17
When the real number has a fractional part, AppleScript follows the same rules as it
follows for the round command’s rounding to nearest option. That is, it rounds to the
nearest whole number except when the fractional part is exactly .5, in which case it
rounds to the nearest even number.
Here are some examples:
3.3 as integer
--> 3
3.7 as integer
--> 4
3.5 as integer
--> 4
4.5 as integer
--> 4
Integers and reals can be freely coerced to text; for example:
1000 as text
--> "1000"
4.3E+17 as text
--> "4.3E+17"
You can also coerce in the other direction, but only if the string contains a correctly
formatted number—any other characters will result in a coercion error:
"1000" as integer
--> 1000
"1000" as real
--> 1000.0
"$1,000,000" as integer
--> Error: Can't make "$1,000,000" into type integer.
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 8: Working with Numbers
231
If you don’t want to specify the exact class of number, AppleScript also allows you to
coerce to the special number pseudo-class. AppleScript then chooses the most
appropriate class for you, depending on whether or not the number has a fractional part:
"43" as number
--> 43
"-3.14" as number
--> -3.14
Example Projects
Let’s finish off with three practical projects that put integers and reals to good use. For
the first exercise, you’ll develop an enhanced rounding command,
round_to_decimal_places, which can round a real to a given number of decimal places.
The second exercise will produce a simple Blackjack game using basic arithmetic and
comparison operators. The final exercise will create a handy kitchen timer application,
using the div and mod operators to perform time-related calculations.
Defining a Round-to-Decimal-Places Command
When you simply round a real number, you get an integer as a result. That’s good for
some things, but what if you want to round to a certain number of decimal places
instead? Take, for example, currency formatting. If you need to calculate a price, you
need two decimal points.
In this project, you are going to use AppleScript to calculate the 7 percent Rhode Island
state sales tax. For a product that costs $4.99, the total cost with tax will be $5.3393.
Using the round command on its own would give you $5, but what you want is $5.34.
The solution involves dividing and multiplying the number before and after rounding it.
Here is the script, which is followed by a line-by-line breakdown:
1.
2.
3.
4.
5.
6.
set the_price to 4.99
set sales_tax to 0.07
set price_with_tax to the_price + (the_price * sales_tax)
price_with_tax * 100
round result rounding as taught in school
set price_with_tax to result / 100
In lines 1 and 2, you assign values to some variables you will use in the script. This is still
a good idea even if the values never change. The sales tax is 7 percent, or 0.07. This
value is assigned to a well-named variable, sales_tax, making its purpose obvious at a
glance, especially if it is used in multiple places in your script.
Line 3 multiplies the price and the sales tax values, and then adds the result to the price
before tax to obtain the exact price with tax included, which is 5.3393.
Lines 4 to 6 perform the rounding operation. In line 4, you multiply the result by 100. You
do this because any real number with two decimal points multiplied by 100 should be
whole. To figure out the number to use, you can raise 10 to the power of the number of
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
232
CHAPTER 8: Working with Numbers
decimal places you want. Get it? You want to end up with two decimal places, so you
do 10^2 to get 100.
To make that result whole, you round it in line 5, using the rounding parameter with the
value as taught in school to ensure that a price ending with half a penny or more
rounds up to the next penny.
To give the resulting number its two decimal places back, you divide it by 100 in line 6.
NOTE: Lines 4 and 5 in the preceding example don’t assign any variables. You could use a
temporary variable if you wanted to, but this example used AppleScript’s special result
variable instead. This is a built-in variable that automatically holds the result of the previous
expression. You can do that here because the result of each expression is only used in the
following line. The result of line 4 is used in line 5, and the result of line 5 is used in line 6.
Chapter 11 will explain this variable in more detail.
Generally, as you math whizzes already know, if you take a number (N) and first multiply
it by another number (M) and then divide it by that same number (M), you get your
original number. You’re counting on that fact, but you’ve added a little twist: you
rounded the number in the middle.
Now that you’ve worked out the basic process for rounding to a fixed number of decimal
places, you need to develop a general-purpose handler that can round to a custom
number of decimal places. The handler, called round_to_decimal_places, will accept
two parameters:
The number to round in the real value class.
The number of decimal places. This will be a small integer that tells the
handler what precision you want. For instance, a value of 2 turns
1.66667 to 1.67.
Script 8–2 shows the complete handler, which is followed by a brief explanation of the
steps.
Script 8–2.
1. on round_to_decimal_places(the_number_to_round, the_decimal_precision)
2.
set multiplier to 10 ^ the_decimal_precision
3.
the_number_to_round * multiplier
4.
round result
5.
return result / multiplier
6. end round_to_decimal_places
I already discussed steps 3 through 5 earlier. You multiply the number you want to
round and then you round it and divide it by the same number to return it to its original
range.
The neat feature here is how you got to the number you need to multiply and divide by.
Line 2 takes the number of decimal places that you want, and raises the number 10 by
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
CHAPTER 8: Working with Numbers
233
that number. For example, if you want to end up with three decimal places, you do this
calculation: 10 ^ 3. The result is 1000, which then is used in the rounding operation.
For example, suppose you want to round 5.1234 to 2 decimal places. Just add the
round_to_decimal_places handler to your script, along with the following command:
round_to_decimal_places(5.1234, 2)
Run the script, and the command returns 5.12.
You can even use a negative integer for the precision, in which case digits to the left of
the decimal point will be rounded to 0 as well as any on the right:
round_to_decimal_places(1234.567, -2) as integer
--> 1200
Licensed by
Jim Kilcullen
2884260
One last thing: notice that line 2 expects the decimal precision value to be a whole
number. What happens if the user then passes a non-whole number by accident?
Well, the multiplier value will not be an exact multiple of 10. For example,
round_to_decimal_places(1.2345, 2.1) would give a multiplier of 125.892541179417.
This would change the number 1.2345 to 155.41434208599 instead of just shifting the
decimal point to the right, giving a final result of 1.231208763823—not what you want
at all!
While you can use this handler as it is, it would be good to protect against this
possibility. The solution is to check beforehand whether the number provided has a
fractional part, and throw an error if it does. The following conditional statement uses the
is_whole_number handler from earlier in the chapter to check the decimal precision
value, and throws an error if it is unsuitable:
if not is_whole_number(the_decimal_precision) then
error "The decimal precision parameter was not a whole number."
end if
Add this code to Script 8–2 immediately before line 2, and the improved
round_to_decimal_places handler is good to go. (When pasting this handler into your
scripts, remember to add the is_whole_number handler as well.)
Blackjack!
To cap off the short random-number topic, I thought it would be appropriate to invite
you to play a little game of Blackjack.
To keep the script short and simple for the sake of the example, I have simplified a few
rules. In the AppleScript Blackjack game, an ace is always 1, cards 2 to 10 keep their
face values, a jack is 11, a queen is 12, and a king is 13.
If this is too much for your purist self, I suggest you add the necessary lines of code to
make the game complete, such as to allow an ace to be 1 or 11.
As for my script, here’s how I went about it: the two players are the dealer and you.
Each of you has a hand of cards. The information regarding that hand is kept in a
record. Each player has their own record that includes two properties labeled total and
Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X, Third Edition. Learn AppleScript: The Comprehensive Gu
Prepared for jim.kilcullen@lifeway.com, Jim Kilcullen
Copyright © 2010 by Hamish Sanderson and Hanaan Rosenthal. This download file is made available for personal use only and is subject to the Terms of Service. Any other use requires
prior written consent from the copyright owner. Unauthorized use, reproduction and/or distribution are strictly prohibited and violate applicable laws. All rights reserved.
234
CHAPTER 8: Working with Numbers
hand. The total property contains your total score that shows whether either of you
reached or passed 21, and the hand property contains a string that’s used to show you
the cards you have and to show the dealer’s hand at the end of the game. In that string,
cards may appear like so: [5][K], meaning you have a five and a king.
NOTE: Notice that I’m storing each player’s information in a compound value called a record,
which is a collection of properties. Each property consists of a unique label (or name), which is
an identifier, and a value. To get or set a property’s value, you refer to it by its label. Records are
often used to package up closely related pieces of information. You can find more details about
records in Chapter 10.
This is how the player’s record typically looks:
{total:18, hand:"[10][8]"}
Later in the script, you’ll use the hand property to display the dealer’s hand to the player,
like this:
display dialog (dealer's hand)
TIP: You can write the above reference using the more common of