fsnotes
fsnotes copied to clipboard
API for plugins/extensions support
To run arbitrary functions on note contents. Plugins would be scripts packaged into a folder (e.g., ~/Library/Application Support/FSNotes/extensions/myplugin/
, and would execute via custom hotkeys.
Some examples for the use of plugins:
- text transformation: convert tabs to spaces; strip HTML tags; format/beautify markup
- exporting: export note to PDF; copy note to clipboard
- connect to external APIs: post note to blog; save note as GitHub gist; validate markup
- snippets: via autocomplete and hotkeys
- themes
~~Rather than build your own plugins API, perhaps FSNotes can adopt an existing plugins ecosystem (VIM, Visual Studio Code, Atom, Sublime Text, etc), and automatically be able to use the many plugins that already exist.~~ This is probably not feasible, see my comments below.
These are a few of the open feature requests that could be solved using a plugin: #487, #484, #438, #303
@gingerbeardman raised issue #328 to discuss adding AppleScript support, but I would consider that a separate feature. The goal of plugins here is not to control FSNotes itself, but to execute an external command with the current note as input (optionally inserting a response back into the note content). A plugin itself could be an AppleScript which in turn controls FSNotes, if it were controllable via AppleScript.
perhaps FSNotes can adopt an existing plugins ecosystem
Could you include a few links to either code or documentation of these plugin systems?
Could you include a few links to either code or documentation of these plugin systems?
I spent a few minutes looking at existing text editor plugin systems. I came to the conclusion it probably will not be feasible to adopt a plugin API from an existing software project, mainly because the APIs will be tightly integrated into the specific functionality provided by each text editor – functionality which FSNotes doesn't (and probably shouldn't) have. Existing plugins designed for these other text editors, which call API methods specific to that text editor, would fail in FSNotes if the same method is not supported.
It may still be possible to emulate an existing plugins API with a subset of its functionality, which would allow very simple existing plugins to still run, but if the user tries to run a plugin with more dependencies of the API it will fail, resulting in a poor user experience. In that case, a plugin migration tool or validator would be required to ensure an existing plugin would work with FSNotes.
I think the best use of existing APIs is simply to use as inspiration for creating a new plugin API for FSNotes. Learn from their mistakes, take the good parts, and create a new API for FSNotes that is optimized for its usage. After all, using ⌃⌘E
a user can launch a powerful external editor anyways. This research would take some time, ideally by someone familiar with the internals and goals of FSNotes (i.e., not me).
Here are links to the plugin documentation for a few open source text editors:
- Textmate bundles
- NeoVIM plugins
- Visual Studio extensions
- Atom packages
- Sublime Text packages
- Eclipse plugins
I also checked with many of the popular note-taking and markdown-specific editor apps. None have an extensible plugins system, except:
- Inkdrop plugins (“an Atom-inspired plugin system”)
- Mailmate bundles
- 1Writer actions
Thanks for those. I haven't looked at all of them, but some of what I saw looks really good. A few thoughts:
- if we go Javascript-only, I think it will be much simpler to implement, and besides, sandboxing would make running, for example, the Perl or PHP binaries really frustrating
- I think it would be awesome to be able to implement the following types of Javascript plugins:
- word counter, reading-age calculator etc (which dynamically update as you type)
- replace the existing (and clunky) auto-bullet/auto-numbering with a Javascript version
- etc
- to allow plugins to do any of those, they'd need to listen to events propagated from the app, and as such would be operating asynchronously; we wouldn't want to bind up the UI waiting for a plugin that might send stuff off over the network for example. I'm not entirely sure right now how you'd code a plugin that couldn't guarantee it has the current state of the document.
Are there possible race conditions with multiple plugins wanting to update the current document? Thoughts from any of you Javascript developers? Am I overthinking it?
A possible solution to the race condition issue might be to have "magic methods" for each event that plugins can use (eg an FSNotes.note.keyUp(key, note)
method), and FSNotes would just call each plugin's implementation of these methods sequentially, with the current state of the document, allowing each plugin a chance to modify the document safely. This would have to be done without tying up the main thread in Swift so the app stays responsive.
I want to add FoldingText as another example implementation. It uses JS. Unfortunately documentation is officially only accessible from within the app, but looking at the code of existing plugins should give a good idea. A few examples from there:
- Character count
- Sort lines ("command")
- Stopwatch ("mode") – I find FoldingText's modes a pretty nice idea to add functionality while keeping it all text, but probably beyond the currently discussed scope.
@sgoumaz I really like the way FoldingText opens notes for its Help > User Guide etc menu items—very cool!
As a text editing experience FoldingText seems more refined than FSNotes.
I totally second this request. Opening to the world of plugins would give FSNotes superpowers!
The project is open source, so any can send pull request, but I don't see much willingness.