Writing Atom plugin in Haskell
Paul Meng
What's Atom
- Github's Editor
- Underlying is Electron, which is based on Webkit
- Programmable Editor
- Rich interactive environment like Emacs but with Javascript
Atom API
- Much easier than Neovim.
- And REPL with the Developer Tool make it easy to see live result.
- API are put under
atom
namespace
- Editor
Javascript call GHCJS
- GHCJS doesn't explicitly support exporting function.
- It requires workaround to make the two side world communicate to each other.
foreign import javascript unsafe "renderMarkdown_ = $1"
js_set_renderMarkdown :: Callback a -> IO ()
Markdown Preview
- Live preview of the markdown content.
- With the help of
markdown
package. Implementing markdown2html is pretty easy.
renderMarkdown :: JSVal -> IO ()
renderMarkdown x = do
let o = Object x
rawMarkdownStr <- getProp "markdownStr" o
let markdownStr = textFromJSVal rawMarkdownStr
let htmlStr = (unpack $ renderHtml $ markdown def $ fromChunks [markdownStr])
setStringProp (JSS.pack "ret") (JSS.pack htmlStr) o
Compile to JS
- Compile to Javascript with GHCJS 0.2
- The target file size is pretty large
stack exec ghcjs -- -DGHCJS_BROWSER -o render.js render.hs
$ ls -lh lib/render.js
-rw-r--r-- 1 mno2 staff 6.0M Jun 12 13:00 lib/render.js
Glue Code in JS
- Use the convention option object to pass the content to compiled JS
- Retrieve the return value from modified object
renderMarkdown(content) {
var option = { markdownStr: content }
window.renderMarkdown_(option);
var html = option.ret;
var outPath = path.resolve(path.join(os.tmpdir(), "star-platium" + ".html"));
fs.writeFileSync(outPath, html, {});
this.element.src = "file://" + outPath;
}
Launching the plugin
atim install --dev .
atom --dev .