ecto (Version 4)
for macOS 10.12 (Sierra) and macOS 10.13 (High Sierra)
ecto has several built-in add-ons that manipulate text in the active editing area, such as for example, Amazon Helper, Flickr Helper, and Scripts. You can write your own add-on. To explain how to, I figure it's best to use a sample add-on. After all, what's the better way to learn how to write an add-on for ecto3 than to see a working example? I uploaded the source code of the iTunes add-on as a 53.8 KB zip file. The iTunes add-on grabs info of the currently playing song in iTunes and returns it as a formatted string to ecto, which then inserts it into the active editing area.
The zip archive contains an XCode project with everything necessary to have an add-on working. You can work right on top of this file, but you'll have to rename source code files and class names to prevent conflicts (see this blog entry for directions).
The meat of the code is one call the add-on gets from ecto:
- (id)addonRequested:(id)delegate selection:(NSString*)selectedText subaction:(NSString*)subaction
ecto calls the addon with selected text or full text from active text area (depending on a setting you define in the add-on) and a delegate. Once done, you'd call the delegate using the selector 'addonFinished' and a string (return nil to cancel the action). All text should be plain text (in HTML or any of the supported formats). If you require feedback from the user, return an object that instantiates a nib and responds to @selector(view) to return a view for display. If you return an object, the delegate will keep it around for as long the delegate is alive, and send any following addonRequested calls directly to the object. There is no need to manage objects you return. The delegate will release when done. Just make sure not to autorelease it.
The iTunes add-on doesn't use a nib when called by the user (Amazon Helper and Flickr Helper do). It just returns text, so it's the easiest type of add-on. It also offers a preferences view so the user can define settings specific to the add-on (via ecto -> Settings -> Tools & Add-ons).
If you're familiar with Objective-C and Cocoa, the project should be decent study material. If you have questions, pose them in the Developer Forum or contact me directly. I'd be more than happy to provide more info, advice or an example add-on that uses a nib.
Some blog systems (Drupal, MovableType, TypePad) provide a blog client (such as ecto) with a list of available text formats. This allows the user to write a post in ecto using, for example Markdown, and have ecto inform the blog system on publish that it should interpret the text as Markdown.
Markdown and Textile formatters are built into ecto, so that when you preview your post the text is correctly converted to HTML. You can, however, create custom formatters for any formats that your blog system uses but isn't handled by ecto (e.g. MathML).
To get you going, I have made the source code of the Markdown formatter available.
Once you've downloaded and unpacked the sample, rename the project. Ideally, you'd use the name of the format provided by your blog system. Let's assume your formatter will be called MathML. In the Finder, rename "Markdown.xcodeproj" to "MathML.xcodeproj". Double-click the file to open it. Make sure to use the Release build configuration. In the Groups & Files list, click on "Markdown" under the "Targets" section. Select File → Get Info. Under "Build", find the values for "Product Name" and "Prefix Header" and rename them. Under "Properties", assign a unique identifier, e.g. com.thirdparty.ecto_mathml and change the principal class to "MathML". Close the Get Info window.
Back in Groups & Files, rename any files containing "Markdown" so that they contain "MathML". You will then have to rename the class names inside those files as well. In other words, class Markdown becomes MathML, and so forth.
Do NOT rename "FormatterInterface.h" and do NOT rename the "ECTOFormatterProtocol" protocol name.
In Markdown.m, you will also need to change the code for "-(NSString*)formatterKey
", "-(NSString*)formatterDescription
" and "-(BOOL)willHandleFormat
".
The formatter plug-in has one entry point: "- (NSString*)formatText:(NSString*)source
". That's where the conversion to HTML happens. For Markdown, I used Perl scripts, which are accessed via a pipe. See the code for details.
Some blog systems, such as WordPress, do not provide a list of formatters. When you preview posts in ecto written for these blog systems, ecto uses a special built-in formatter, Generic.formatter. It analyzes the text and will format accordingly (it recognizes Markdown and Textile). You could write your own Generic.formatter and install it into ~/Library/Application Support/ecto3/formatters/ and it would override the built-in version.
If you have any questions about writing a formatter, please visit the Developer support forum.
What better way to learn how to write a notifier add-on for ecto3 than to see a working example? I uploaded the source code of my twitter add-on as a 104 KB zip file. The archive contains an XCode 2 project with everything necessary to have a notifier add-on working. You can work right on top of this file, but you'll have to rename source code files and class names to prevent conflicts (see this blog entry for directions).
The meat of the code is one call the add-on gets from ecto:
- (void)processNotification:(int)type data:(id)data
The various types and the data you can expect is documented right in the code. If you're familiar with Objective-C and Cocoa, the project should be easy study material. If you have questions, pose them in the Developer Forum or contact me directly. I'd be more than happy to provide pointers.
Smart observers will note that the add-on header file also applies to ecto3 add-ons that let you manipulate or insert text (the Amazon and Flickr Helper add-ons are using this). I'll release a sample for this type of add-on soon.
One of the reasons I rewrote ecto from the ground up into what is now available as ecto3 beta is to allow for third-party add-ons. I wanted the application to become more modular and have a plug-in architecture. The first type of add-on that I am going to explain is the uploader. Some blog-systems allow users to upload files using either the appropriate XML-RPC or Atom call, but Blogger and a slew of others do not support that. For those alternative means should be available. ecto3 already has a built-in add-on that lets you upload images to Flickr. In this blog entry I will provide sample uploader code and directions on how to write your own. If you have the Cocoa skills, you could write an FTP or Picasa uploader.
The first step would be to download and unpack the sample uploader. It actually does not upload, but gives you a basic framework to work with. Once you've unpacked the sample, it's a good idea to rename the project. Let's assume your uploader will be called MyUploader. In the Finder, rename "SampleUploader.xcodeproj" to "MyUploader.xcodeproj". Double-click the file to open it. In the Groups & Files list, click on "SampleUploader" under the "Targets" section. Select File → Get Info. Under "Build", find the values for "Product Name" and "Prefix Header" and rename them. Under "Properties", assign a unique identifier, e.g. com.thirdparty.ecto_myuploader and change the principal class to "MyUploader". Close the Get Info window.
Back in Groups & Files, rename any files containing "SampleUploader" so that they contain "MyUploader". Rename the "SSUUploadWorker" files to something different as well. You will then have to rename the class names inside those files as well. In other words, class SampleUploader becomes MyUploader, and so forth.
Do NOT rename "UploaderInterface.h" and do NOT rename the "ECTOUploaderProtocol" protocol name.
In SampleUploader.m, you will also need to change the return value for "-(NSString*)uploaderKey
" and "-(NSString*)uploaderDescription
".
The uploader plug-in has two entry points. The first one is a method called when the user is accessing settings for a given attachment that uses the uploader: "-(id)uploaderRequested:(NSMutableDictionary*)settings
". You can use this to allow users to specify a variety of general preferences (which you would store in NSUserDefaults) or attachment-specific settings, which are stored in the provided dictionary. See SampleUploaderSettings.m for an example.
The actual upload happens with a call to -(void)uploadData:(NSDictionary*)data delegate:(id)del errorSelector:(SEL)err endSelector:(SEL)end statusSelector:(SEL)stat
. All the data you need for upload is provided in the "data" dictionary, which also includes any of the settings stored in the previously discussed method. The SampleUploader.m file lists the various available keys and how you can use them. It allocates an SUUploadWorker class, which does the actual upload. Once this object has done its job, a delegate call is made back to ecto to inform of the result. See -(void)upload
for an example of what you need to return to ecto.
The most simple adaptation would only require changing -(void)upload
in SUUploadWorker.m and writing code for the actual upload in there.
If you have any questions about writing an uploader, please visit the Developer support forum.