CPIA Script User Guide
CPIA Script is using Python. CPIA Script provides three things:
- a UI that makes it easy to create and run scripts
- a set of conveniences that hide the complications inside our application
- a class that simulates a User to create low level events
Lets start by looking at the user interface.
Script User Interface
To start scripting, you currently must select an item from the Test menu -- "Show Scripts in the Sidebar"
You use the "Scripts" collection to view all the Scripts in the repository. We've created some useful ones for you. Specifically, there's a script connected to the F1 key that creates a new Script for you. You can immediately start typing into the body of this new script, and then execute it using the command-s shortcut to the Test menu item 'Run "Untitled"'. Scripts have a couple of attributes displayed in the Detail View. These include a Function Key used to activate the script, and a "Test" boolean. One of the unit tests launches Chandler and runs all the scripts marked as test scripts, for a simple form of automated testing. Function key script triggering lets you write scripts that interrogate the current focus and other useful things because you can run the scripts without needing to have your script selected.
Scripts themselves are ContentItems that keep their script text in the body attribute (where notes go), and keep track of the last time they were run, etc.
There are a couple of different ways to invoke a script:
- When running Chandler from the command line using the --testScript parameter:
release/RunChandler --testScript This runs all the scripts with the "Test" attribute set, to test Chandler.
- From the command line using the --scriptFile parameter:
release/RunChandler --scriptFile="/Users/OSAF/script.txt"
- By pressing a function key (in the range F1 through F24)
- To make the function key work, put your script in the body of any Chandler Note item, and set the Function Key attribute to the number of the function key you want to connect the script to.
- By selecting the script, and choosing the Test/Run "script name" menu item, which is connected to Command-S.
Scripts are Python code. As such, it's convenient to use file-based Python tools to edit scripts. You can do this by saving the script to a file, and then editing that file with your regular Python editor instead of editing it in the Detail View of the script. Whenever scripts are loaded or executed, the scripting system synchronizes the script in the repository with the script in the file, with the most recently changed version winning out. This makes it easier to debug scripts, set breakpoints, and do the other things normally done in the course of Python development.
Script Conveniences
A Script is really just some python code that gets executed in an environment that has some convenient definitions for you to use.
These conveniences fall into two categories:
- Access to Chandler's features that are complicated by internal implementation details
- Simulating User actions, like typing some text into a field
An example of the first category is getting access to the Summary View. The way CPIA is implemented, there may actually be several Summary Views, but only one of them will be rendered at any given time. So finding the current view is non-trivial. With the conveniences, you can essentially just say
convenience.summary
to get the summary view.
You get at the Chandler conveniences using the app_ns(view) function. This creates and returns an AppProxy object, which is a proxy to the osaf.app namespace inside the specified view. You can leave off the view parameter and it will default to the UI Repository View - the view used by Chandler's UI. The AppProxy object has attributes that automatically lookup all the major blocks in Chandler:
- sidebar - proxy to the Sidebar
- summary - proxy to the Summary View
- calendar - proxy to the Calendar View
- appbar - proxy to the Application Toolbar
- markupbar - proxy to the Markup Toolbar
- detail - proxy to the Detail View
- root - proxy to the Main View Root
The root and detail attributes are special. The detail attribute gives you a proxy that has a bunch of blocks from the detail view as its attributes:
- start_time -- the calendar event start time edit field
- start_date -- the start date
- location -- the location block
- title -- also known as the Headline area etc
The RootProxy has some extra behavior. It is the block that posts commands that you send to Chandler. All defined BlockEvent objects that are available through the eventsForNamedLookup attribute are methods of this object. So you can say app_ns().root.New() to create a new Note, for example. See the command reference below for a list of commands available as methods of the RootProxy object.
The AppProxy actually maps all named blocks onto its attributes, so you can say app_ns().MiniCalendar to get the MiniCalendar block for example.
Command Reference
CPIA BlockEvents that are available as "named" events are available as commands in CPIA Script. But you need to be somewhat careful using them:
- Some require parameters, which is a bit tricky. You can either use the syntax used internally by CPIA (pass a single dictionary for the parameters), or pass named parameters, or both.
- Some work, but not in all contexts. Take "Remove" for example. You can use it to remove your "All" collection - something the UI won't normally let you do.
Below is a list of all the CPIA Events available in the system.
- Bold commands are tested and work
- Italic commands don't work or should not be used
- Plain items have not yet been investigated
- About() - bring up the "about" box
- AcceptShare()
- ActiveateWebserver - activate the test feature making Chandler a Web server
- AddAllAdditionalViews() - adds all the extra views to the sidebar (CPIA view, Block Demo view, and Repository view)
- AddCPIAView() - adds the CPIA viewer to the sidebar
- AddDemoView() - adds the Block Demo view to the sidebar
- AddRepositoryView() - adds the Repository view to the sidebar
- AddText()
- AddToSidebarWithoutCopying()
- AddToSidebarWithoutCopyingAndSelectFirst()
- AddToSidebarWithoutCopyingOrCommiting()
- ApplicationBarAll() - switches to the All view
- ApplicationBarEvent() - switches to the Calendar view
- ApplicationBarMail() - switches to the Email view
- ApplicationBarTask() - switches to the Tasks view
- BackupRepository() - invoke the test feature to create a repository backup
- CertificateImportBlock() - imports a certificate PEM file
- CertificateViewBlock() - add the Certificate view to the sidebar
- ChangeLayout()
- CheckRepository() - same as the menu item
- ChooseAttributeEditorsTab()
- ChooseButtonsTab()
- ChooseChandlerMainView()
- ChooseControlsTab()
- ChooseCPIATestMainView()
- ChooseHTMLTab()
- ChooseIntroTab()
- Close() - close the topmost window, which may quit Chandler
- CommitRepository() - commit changes to the repository
- Copy() - copy the selected item to the clipboard
- CopyCollectionURL()
- Cut() - cut the selected item
- CycleTabs()
- EditAccountPreferences() - bring up the account preferences dialog
- EditCollectionRule() - bring up a dialog to let you edit the selected collection's rule
- EnterPressed()
- ExportIcalendar() - brings up a dialog box for exporting the calendar
- GenerateContentItems() - generates many items of each kind for testing purposes
- GetNewMail() - attempts to get new mail according to the account preferences
- i18nMailTest()
- ImportIcalendar() - brings up a dialog box for importing an ICS file
- ImportImage() - import an image to create a Photo item
- ManageSidebarCollection()
- MimeTest() - same as the menu item
- New() - create and select a new Content Item (defaults to Note)
- NewAmazonCollection() - same as the menu item
- NewAmazonWishList() - same as the menu item
- NewCalendar() - create and select a new calendar Event
- NewContact() - create a new Contact
- NewFlickrCollectionByOwner() - same as the menu item
- NewFlickrCollectionByTag() - same as the menu item
- NewItemCollection() - create and select a new Item Collection
- NewMailMessage() - create and select a new Mail Message
- NewNote() - create and select a new Note
- NewTask() - create and select a new Task
- NewZaoBaoChannel() - same as the menu item
- Open()
- Paste() - paste the contents of the clipboard into the selection
- Preferences()
- Print() - same as the menu item
- PrintPreview() - same as the menu item
- Quit() - exit the application (Often crashes on a debug build)
- Redo()
- ReloadParcels() - same as the menu item
- ReloadText()
- ReminderTime()
- Remove()
- RequestSelectSidebarItem()
- Resynchronize() - Resynchronize the Detail View
- RunScript()
- SelectedDateChanged()
- SelectItemBroadcast()
- SelectItemBroadcastInsideActiveView()
- SelectWeek()
- SendMail()
- SendShareItem()
- SetContents()
- ShareCollection() - obsolete: use ShareSidebarCollection()
- ShareItem()
- ShareSidebarCollection()
- ShareTool() - displays the share tool
- SharingImportDemoCalendar()
- SharingSubscribeToCollection()
- ShowHideApplicationBar() - same as menu item
- ShowHideSidebar() - same as menu item
- ShowHideStatusBar() - same as menu item
- ShowPyCrust() - brings up an interactive Python shell
- StartProfiler()
- StopProfiler()
- SyncAll() - same as Sync All button
- SyncCollection()
- SyncWebDAV()
- TogglePrivate()
- ToggleSharingActive()
- UnpublishSidebarCollection() - same as the Collection/Unpublish menu item
- UnsubscribeSidebarCollection() - same as the Collection/Unsubscribe menu item
- Undo()
- WxTestHarness()
Item Selection
If you want to select an item in a Table, just call the select() method on the table object, passing in the item to be selected. The summary view supports named lookup, so you can use name= to select an item by name. Note that this feature is in Chandler itself, not CPIA Script, and it's likely to change as Chandler evolves. E.g. select should probably accept a list, so multiple items can be selected.
We'll need to add an implementation of select for the Calendar View.
Simulating User Actions
There's a User class in the conveniences that help you simulate user actions. All the methods in this class are class methods, so you never need to instantiate the User class, you can just call the methods directly. The methods are:
- emulate_typing(string, etc) -- emulate the user typing a string. There are additional parameters not described here.
- emulate_return(block) -- emulate the user pressing the return key in the given block
- emulate_click(block) -- emulate the user pressing and releasing the left mouse button in the given block.
So you can say User.emulate_click(app_ns().detail.location) to click on the location block of the detail view.
More Information
For more detailed information about specific features of CPIA Script, look at the code. The entire implementation is now in one file: scripting.py in the osaf.framework module.