]>
Commit | Line | Data |
---|---|---|
1 | # API Notation Updates | |
2 | ||
3 | A few years ago I created an API notation to use with software specification documents: Back then I was working in a team that relied heavily on software specifications, and we were maintaining projects in objective-c, ruby, and javascript, so the notation emerged out of the need to communicate the public APIs in a way that was generic enough to make implementation in any language simple, while concise enough to avoid integration issues. | |
4 | ||
5 | For example, I could use it to describe the library I use to build this blog[1] | |
6 | ||
7 | ``` | |
8 | // Library to generate an ephemeral html blog with a gemini archive | |
9 | Blog | |
10 | -max_posts <Int> | |
11 | -posts_directory <String> | |
12 | -archive_directory <String> | |
13 | -static_directory <String> | |
14 | -templates_directory <String> | |
15 | -remote_config <String> | |
16 | #add(post_location <String>) => Promise<Void> | |
17 | #update(post_location <String>) => Promise<Void> | |
18 | #publish(host <String>) => Promise<Void> | |
19 | #publish_archive(host <String>) => Promise<Void> | |
20 | #add_remote(remote <String>) => Promise<Void> | |
21 | #remove_remote() => Promise<Void> | |
22 | #sync_down() => Promise<Void> | |
23 | #sync_up() => Promise<Void> | |
24 | #generate() => Promise<Void> | |
25 | ``` | |
26 | ||
27 | => https://git.sr.ht/~rbdr/blog/tree/main/item/lib/blog.js [1] A Javascript implementation of that API | |
28 | ||
29 | I had been using it unchanged for almost ten years, but recently decided to drop a specific symbol for callbacks, and instead add a "Throws" symbol #>. You can see the definition here, or in its home page[2] | |
30 | ||
31 | ``` | |
32 | // Anything after two forward slashes is a comment | |
33 | NameOfClass.WithPossibleNamespace | |
34 | + class property | |
35 | - instance property | |
36 | ~> listened events (socket) | |
37 | +> listened events (class/module) | |
38 | -> listened events (instance) | |
39 | <~ dispatched events (socket) | |
40 | <+ dispatched events(class/module) | |
41 | <- dispatched events (instance) | |
42 | :: class method | |
43 | # instance method | |
44 | ||
45 | Other symbols | |
46 | => returns | |
47 | #> throws | |
48 | [xx] optional | |
49 | <data type> | |
50 | ||
51 | Recommended order: class first, then sockets, then instance. Internally: | |
52 | Properties, events, methods. | |
53 | ``` | |
54 | ||
55 | One of the patterns that I started using for functions is to instead define the whole function signature as part of the type definition. So for example, if you have a method that receives a function as an argument, you could write the following: | |
56 | ||
57 | ``` | |
58 | GenericManipulator | |
59 | #manipulate<T>(input T, manipulator<T>(input T, options <ManipulationOptions>) => T #> ManipulationError) => T #> ManipulationError | |
60 | ``` | |
61 | ||
62 | I've found this pattern covers most cases where I need to pass a function. | |
63 | ||
64 | In slightly related news, since I've recently moved fully to using `neovim`, I've also created a tree-sitter parser[3] that you can use as a neovim plugin. It was really fun to learn, but the documentations was clear and easy to follow. A bit less easy to follow was how to get the syntax highlighting to actually work with neovim, but it ended up working. | |
65 | ||
66 | => https://www.unlimited.pizza/api.html [2] API definition | |
67 | => https://git.sr.ht/~rbdr/tree-sitter-api-notation [3] tree-sitter parser and neovim plugin. | |
68 | ||
69 | If you use other editors, there's older versions of the plugin available for vim[4], vscode[5], and TextMate / Sublime Text[6]. They don't support the #> throws notation. | |
70 | ||
71 | => https://git.sr.ht/~rbdr/api-notation.vim [4] Syntax for vim | |
72 | => https://git.sr.ht/~rbdr/api-notation.vscode [5] Syntax for vscode | |
73 | => https://git.sr.ht/~rbdr/api-notation.tmLanguage [6] Syntax for TextMate and Sublime text |