Writing an action
Previously
We set up Xcode for Quicksilver plugin development, created a Quicksilver plugin project and got familiar with the QSPlugIn portion of the Info.plist file.
We’ve introduced ourselves to Quicksilver, and told it some fundamental information about the plugin we’re making in the QSPlugIn section of the Info.plist file associated with the Quicksilver project.
In this tutorial, we look at the procedures involved in specifying and writing an action for Quicksilver.
QSActions
Communicating our intentions
Writing an action for Quicksilver couldn’t be easier. In fact, there are only two steps in this “How to” guide. Firstly, it’s off to the all-important Info.plist; then we’ll finally begin writing our code.
You wont find a QSActions key in the Info.plist file. It’s named to QSActionsTemplate by default. This is to stop Quicksilver parsing the default data which is automatically added by creating a new project. If we’re writing an action, though, we’ll definitely want to make use of it.
Find the QSActionsTemplate key in the Info.plist file. It’ll look similar to the following, with the instances of “test” replaced with whatever you named your project:
<key>QSActionsTemplate</key>
<dict>
<key>testAction</key>
<dict>
<key>actionClass</key>
<string>testAction</string>
<key>actionSelector</key>
<string>performActionOnObject:</string>
<key>directTypes</key>
<array>
<string>testType</string>
</array>
<key>name</key>
<string>Action: test</string>
<key>validatesObjects</key>
<false/>
</dict>
</dict>
Make sure to rename the QSActionsTemplate key to QSActions. Configure the QSActions key as follows (remember “test” from now on is replaced with your project name):
- testAction
- Rename the testAction key to whatever you want to call your action. This is only internal - the user wont see this, but think of something that’ll tell you what this action does when you’re looking at it. We’ll call this the real name of the action. Descriptive names are especially important when working with multiple actions in a single plugin.
- actionClass
- You have the testAction class already created for you (in the testAction.h and testAction.m files). Double check that they exist and are identical to the value under actionClass.
- actionSelector
- If you’re going to have multiple actions or multiple methods, decide now what you’re going to call your method for this particular action and stick the value under the actionSelector key. If you’re only planning on having one action, the default
performActionOnObject:should be fine. (If you want to have an indirect object passed to you as well, you’ll need a method in the formperformActionOnObject:withIndirectType:. More on this later.) - alternateAction
- If you wish to specify an alternate action, make sure you actually have another action in your plugin. Simply add a string with the name of the action to this key. Not the value for the name key, but the real name of the action.
- directTypes
- Add the types of inputs you want to be working with under the directTypes key. It’s an array of strings that can take values such as NSFilenamesPboardType, NSURLPboardType, NSStringPboardType or Apple URL pasteboard type. A list of allowed types includes:
- *
- Apple URL pasteboard type
- NSFilenamesPboardType
- NSStringPboardType
- qs.action
- qs.catalogentry
- qs.command
- qs.process
- directFileTypes
- If you’re using NSFilenamesPboardType as a directType and you only want files of a specific type, specify directFileTypes as an array containing strings with the extensions you want to allow (eg.
png,pdf,app, etc.) - indirectTypes
- Similar to directTypes, but only applies if you actually want an indirect object passed to your plugin.
- indirectOptional
- A boolean value specifying whether the selection of an indirect is required for the action to be called.
- name
- The name that the user will see when using your action from Quicksilver.
- description
- An (optional) brief description of what the action does.
- enabled
- A boolean value determining whether your plugin is enabled by default.
- icon
- An icon for your action. Can be in the form com.developer.app.
- precedence
- If you’d like your plugin to have more importance than other actions, enter an integer here. Normal settings are from 0 to 4. The higher the number, the more importance is given to your action. This is especially useful if your plugin deals with a source that no other plugin deals with. In that instance, you’d want your action to have higher authority than the standard ‘Open’ and ‘Run’ actions for that particular source.
- reverseArguments
- If set to true, Quicksilver will reverse the direct and indirect selectors before passing you the data. This comes in handy if you want to provide two actions that are the reverse of each other so you only need to write one method. For example,
[Text] Find with... [Search Engine]is the reversed version of[Search Engine] Search For... [Text]. They both use the same selector, but the first one gets the direct and indirect objects swapped around. - displaysResult
- If true, Quicksilver will take the value you return in your method, and set it as the direct object.
- runInMainThread
- Whether the action needs to be forced to run in the main thread. Recommended for timers or actions that calculate a delay.
- hidden
- Boolean specifying whether the action is visible (hence directly usable) by the user. This field is generally best left out unless you’re writing an internal action.
- disabled
- Whether the action is disabled by default when the plugin is activated. Boolean.
- validatesObjects
- True or false. True if your plugin validates the objects passed to it, false otherwise.
Now for some Cocoa
Writing the code
Yes, after having our head buried in the Info.plist, we finally get to write some code.
The class we declared as our actionClass in the Info.plist is the one that needs to house the method for the action.
Open up testAction.m (you still need to keep replacing ‘test’ with your project name). The file currently looks something like:
//
// testAction.m
// test
//
// Created by Ankur Kothari on 15/02/07.
// Copyright Vacuous Virtuoso 2007. All rights reserved.
//
#import "testAction.h"
@implementation testAction
- (QSObject *)performActionOnObject:(QSObject *)dObject{
return nil;
}
@end
All you have to do, is take the QSObject which is passed to you in the form of the pointer dObject, do something with it, and return something! In fact, you don’t necessarily even have to return anything. This is the part of the tutorial that you put on your Cocoa hat and let your imagination, creativity and logic run wild. Write that amazing action!
If you don’t like to mess around until you’ve figured out how to do something, here’s an example of a Quicksilver action that takes a string object, then returns the same string with ” hello” appended to it. (Note that if you want to build the following code as a trial or test, you’ll need to configure the Info.plist using the information provided above.)
//
// testAction.m
// test
//
// Created by Ankur Kothari on 15/02/07.
// Copyright Vacuous Virtuoso 2007. All rights reserved.
//
#import "testAction.h"
@implementation testAction
- (QSObject *)performActionOnObject:(QSObject *)dObject{
QSObject *result;
NSString *dWithHello;
dWithHello = [NSString stringWithFormat:@"%@ hello",[dObject stringValue]];
result = [QSObject objectWithString:dWithHello];
return result;
}
@end
Build and run
Double-click on the built plugin (test.qsplugin) to have Quicksilver install it. Passing a string such as “is this plugin working?” should get an output of “is this plugin working? hello“. Try passing a file or folder. The string you’ll get will be the name of the file / folder with ” hello” appended to it.
Take careful note of the following:
- The string is extracted from dObject using the
stringValuemethod. - An object of any type is extracted from dObject using … methods.
- An instance of a QSObject is created using the method objectWithType: where Type is the type of object you wish to add to the QSObject. Eg.
[QSObject objectWithString:@"A string"]; - If the method returns a non-null value, it must be as a QSObject.
That’s it! You are now fully qualified to develop Quicksilver actions using Cocoa, in your familiar Xcode development environment.
If you’re very adventurous, look through the source code for other plugins you can find, and browse through the Info.plist files for some of the plugins you have (they’ll be a bundle with the extension of .qsplugin).
Have fun, and stay tuned for further tutorials on Quicksilver plugin development.
Also in this series
Info.plist - QSPlugIn
A introduction to the Info.plist and our first encounter with the QSPlugIn key. Teaches the initial steps required to ensure communication between Quicksilver and your plugin occurs correctly.
Quicksilver plugins in Objective-C
A guide to obtaining the required resources for Quicksilver plugin development in Xcode. Also runs through setting up Xcode to make creating plugins easier.
Quicksilver Interface Creation
A thorough guide on the techniques to create a working Quicksilver interface. Includes an Xcode project template to minimize the effort required.
5 Comments so far
Leave a commenthi im mohan i am having problems.: URLsWithURL
revealed by Velopliv on November 28, 2009 11:31 am | Permalink
Leave a comment