]> git.r.bdr.sh - rbdr/blog.unlimited.pizza/blob - posts/2/api_notation_updates.gmi
blog-sync-up-1704232830559
[rbdr/blog.unlimited.pizza] / posts / 2 / api_notation_updates.gmi
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