Chocolat can be extended plugins called mixins. Mixins are written in JavaScript and run on node.js.
For this tutorial, we'll be writing a mixin that looks up a word on wikipedia and displays the wikipedia article. Like the OS X dictionary popover.
Sounds complex? This is the entire code:
Hooks.addMenuItem("Go/Search in Wikipedia", "cmd-ctrl-w", function() {
Recipe.run(function(r) {
var wordrange = r.wordRangeForRange(r.selection);
var word = r.textInRange(wordrange);
var win = new Popover(Editor.current(), wordrange);
win.size = { width: 320, height: 480 };
win.url = 'http://en.m.wikipedia.org/w/index.php?search='
+ encodeURIComponent(word)
+ '&title=Special%3ASearch';
win.run();
});
});
Chocolat looks for mixins in three places:
~/.chocolat/mixins
~/Library/Application Support/Chocolat/Mixins
Chocolat.app/Contents/SharedSupport/mixins
I'll be using ~/.chocolat/mixins
, but you can use Application Support if you prefer.
So let's get started...
mkdir -p ~/.chocolat/mixins/wikipedia.chocmixin
choc ~/.chocolat/mixins/wikipedia.chocmixin/init.js
First, we need to add a "Search on Wikipedia" menu item to the Go menu:
Hooks.addMenuItem("Go/Search on Wikipedia", "cmd-ctrl-w", function () {
Alert.show("Hello World!");
});
Save that and—like magic—the "Search on Wikipedia" menu item will appear in the Go menu! Click it.
OK, so we want to look up the current word on Wikipedia. For that, we need to find the current word. How?
The Recipe class is a one-stop-shop for text manipulation. A recipe lets you modify text and selection safely and atomically.
Each Recipe starts out with a call to Recipe.run()
, to which you pass a function:
Recipe.run(function(r) {
// do something with r
});
The r
object is the instance of the Recipe
class. To find the current range, call .wordRangeForRange()
on the recipe and pass it the current selection. Chocolat uses Cocoa's idea of a "selection", a text cursor is just a selection of length 0.
Recipe.run(function(r) {
var wordrange = r.wordRangeForRange(r.selection);
});
Getting the string for that range is another method on the recipe.
Recipe.run(function(r) {
var wordrange = r.wordRangeForRange(r.selection);
var word = r.textInRange(wordrange);
});
All together now:
Hooks.addMenuItem("Go/Search on Wikipedia", "cmd-ctrl-w", function () {
Recipe.run(function(r) {
var wordrange = r.wordRangeForRange(r.selection);
var word = r.textInRange(wordrange);
Alert.show("Your nearest word is '" + word + "'!");
});
});
Since Chocolat's scripting language is JavaScript, it's only fitting that the UIs are made using HTML.
Think about that. You can display any UI in Chocolat that you can construct using HTML, CSS and JS. Cool!
For the purposes of this tutorial, we just want to show a page from wikipedia.org in a popover. To that, create a new instance of Popover and set the url
property.
// Create a popover attached to the current editor
// and positioned over the word range we found earlier
var win = new Popover(Editor.current(), wordrange);
// Set it to the size of an iPhone screen
win.size = { width: 320, height: 480 };
// Do a search on m.wikipedia.org
win.url = 'http://en.m.wikipedia.org/w/index.php?search='
+ encodeURIComponent(word)
+ '&title=Special%3ASearch';
// Show the popover
win.run();
That's all there is to it. Add that code to the recipe code and try looking something up.
Hooks.addMenuItem("Go/Search in Wikipedia", "cmd-ctrl-w", function() {
Recipe.run(function(r) {
var wordrange = r.wordRangeForRange(r.selection);
var word = r.textInRange(wordrange);
var win = new Popover(Editor.current(), wordrange);
win.size = { width: 320, height: 480 };
win.url = 'http://en.m.wikipedia.org/w/index.php?search='
+ encodeURIComponent(word)
+ '&title=Special%3ASearch';
win.run();
});
});
So you've made the world's best mixin and want to make it available to everybody. Simple!
Open Actions › Install Extras to see your mixin among everybody else's.
Chocolat uses the CommonJS package.json format. You do not have to include a package.json file with your mixin, but it's good manners if you want to distribute it.
Everybody always asks me why the hell would you choose JavaScript? It's not because we're hipsters—and we certainly don't think JS is perfect. The short answer is that we tried everything and node.js is the only thing that worked.
it's Fast. Google has done a great job. V8 is one of the fastest VMs out there, next to LuaJIT and the JVM.
it's Easy to Embed. V8 definitely has the best API of any language implementation I've tried. (CPython has the worst BTW. It's almost worse than OpenSSL)
it has Batteries Included. Unlike Lua, which would be a great language if it weren't so bloody useless. Want to do an http request? Find a library. Splitting a path? Find a library. Don't even think about finding the SHA-1 of something. Ugh.
it's Well Known. There are other languages, but they generally are not well known enough. A Clojure-based API would be awesome ...for the one guy who knows Clojure.
Everybody knows JavaScript.