#592 #1457 #1294 #1188 #1187 #1195 and others all raise the issue of plugins providing language services to Geany.
There have been various discussions in the past on the subject with no conclusion. So its time to approach it again and this issue is intended to do that (without hijacking any of the above issues/PRs).
Note the purpose is first to DESIGN the API so that it can be implemented progressively without spamming committers with huge changes to core Geany, and without the first plugin to use any of the API having to implement far more than it needs to.
Since I come from an Aerospace background let me initiate the formal requirements-design-implement process that I am used to, by suggesting some terminology and then requirements:
# Terminology
- A "feature" is something Geany does that is or could be language specific, eg autocomplete, indentation, styling. When referring to a "feature" below it is understood that it is specific to a filetype unless otherwise noted.
- A "filetype support plugin" is a plugin that provides some support for one or more features for the programming language the filetype supports. (Whilst most of the rest of the world calls it "language" support, Geany calls the language specific things "filetypes" so lets keep it consistent).
- There are two steps in starting a plugin "loading" where information needed for the plugin manager dialog is gathered and "activation" when the user selects the plugin in the dialog.
- A "request" is an interaction initiated by Geany for support from the plugin (eg by calling a plugin function)
- A "reply" is the data sent back as a result of a "request" (eg as function return data)
- A "notification" is an interaction initiated by the plugin (eg by calling a Geany function)
# Requirements
- On activation (not loading), filetype support plugins must be able to inform Geany of the service(s) they provide and the filetypes(s) those services are for.
- Geany should provide at least the current capabilities for features that no plugin has offered to provide.
- On de-activation, filetype support plugins must be able to inform Geany that their services are no longer available, however it is probably better if Geany can automatically handle loss of the services and fall back to its default behaviour.
- Currently Geany does not mediate any resources shared between plugins, so it is not proposed that Geany will mediate between multiple filetype support plugins trying to provide the same feature, it can be UB if first wins, last wins or something else, except Geany should not crash.
- The default Geany behaviour for some features may not need to be totally replaced by the plugin, just tweaked. The API must be designed to allow both behaviours, with the plugin specifying which it provides for each reply.
- For all features, Geany should always allow replacement of its default behaviour by a plugin, Geany does not know what weirdnesses programming languages may come up with and should not enforce rules from one language on another where it may not be appropriate. (C++ is NOT C, and Haskell even less :)
- It is up to the implementation of the feature in Geany if it allows tweaking, and what and how that is communicated from the plugin
# Preliminary Design Notes
This is NOT a complete design, just a start.
- My first thought was to use GTK signals, its probably not appropriate to have a signal for each feature for each language, but it is possible for there to be one signal per feature and the plugin callbacks then need to check the filetype of the current document and return false if its not one they handle, so the next plugin callback can be invoked. Given that an individual user probably won't invoke a large number of filetype plugins at once this may be acceptable, even with the additional overhead if the plugins are in languages other than C (eg Python).
- I am not enough of a G* expert to comment on how simple passing data from and to signal callbacks is, for example whilst features like indentation or formatting can just manipulate the Scintilla buffer, for features like autocomplete the plugin needs to return a list of options.
- Since Geany is single threaded and not re-entrant, notifications realistically can only be provided from asynchronous operations occurring in other threads via the mainloop idle-add mechanism.
Feel free to expand this further.