I had a look at the code in ```build.c``` and tried to understand what it's doing. This is how I understood it:
If someone (a plugin) wants to re-write the build menu it would have to call ```build_menu_update``` and then the menu items are re-written according to the magic/selection process described above.
If we want to add plugins to be a build command source we would need to define a new ```GeanyBuildSource```, e.g. ```GEANY_BCS_PLUGIN```.
I'm not sure where the commands for the various sources are saved in memory. I assume the pointers to the commands are these: ``` /* the various groups of commands not in the filetype struct */ static GeanyBuildCommand *ft_def = NULL; static GeanyBuildCommand *non_ft_proj = NULL; static GeanyBuildCommand *non_ft_pref = NULL; static GeanyBuildCommand *non_ft_def = NULL; static GeanyBuildCommand *exec_proj = NULL; static GeanyBuildCommand *exec_pref = NULL; static GeanyBuildCommand *exec_def = NULL; ``` So e.g. ```exec_proj``` holds the commands for the prjoject and does not point to one command but to an array of 9 commands (maximum?).
For the case that there is more than one active plugin wanting to be a GeanyBuildSource I wonder if it wouldn't be better to call a function which is doing the decision for the plugins and returns the list of commands that won.
Also if I understood it correctly the build dialog can be re-used as it saves the set commands into ```dst``` which in this case would need to point to the memory area for the workbench plugin (using function ```GtkWidget *build_commands_table(GeanyDocument *doc, GeanyBuildSource dst, BuildTableData *table_data, GeanyFiletype *ft)```.
So what about exposing only one pointer, e,g, ```GeanyBuildCommand *exec_plugins = NULL;``` to geany-plugins and call some function which is doing the work of ```return_cmd_if``` for the plugins? And as @elextr suggested put some registration/priority handling/arm wrestling code to the shared utils lib in geany-plugins.
Just an idea/brainstorming. Maybe I understood some things wrong, let's see.