On Mon, Aug 29, 2016 at 5:14 AM, Matthew Brush mbrush@codebrainz.ca wrote:
Hi All,
Related to my previous mail, and assuming it is somewhat reasonable, I would like to propose a list of initial features that will be useful to allow plugins to provide, in no particular order:
Syntax Highlighting
Most likely using an API based on/similar to Scintilla's "container lexers".
At the minimum, it could have a callback something like:
gboolean (*highlight)(GeanyPlugin*, GeanyDocument*, guint start_pos, guint end_pos, gpointer user_data);
As with Scintilla's "container lexer", it would just tell the provider what and where to highlight. It might be pointless providing `end_pos` it could probably just highlight a whole line at time (maybe like Scintilla's 'style-needed' notification).
If the providers are to setup their own colour schemes and such, then it may be required to add a callback such as:
gboolean (*init_styles)(GeanyPlugin*, GeanyDocument*, gpointer user_data);
for the plugin to configure all the Scintilla styles as it wishes. This will probably require some kind of conflict avoidance scheme if it is to support multiple providers providing the same feature. Perhaps it could also pass the start style ID the provider can use, and it could tell Geany the maximum style that it ended up using.
Sidebar Symbol Tree
Could provide some API functions to populate the tree by plugins providing the needed information. The nesting could be handled by passing a scope path similar to GtkTreePath or TagManager's `::` delimited scope string, which would be parsed/expanded to apply to the right tree node.
The callback function for the provider might be like:
gboolean (*populate_symbols_tree)(GeanyPlugin*, GeanyDocument*, guint cursor_pos, gchar **current_node_path /* out */, gpointer user_data);
When the providers are called in to, they could use a function something like this:
void tagbar_add_node(const gchar *name, guint line, const gchar *signature, const gchar *scope_path, GeanySidebarIcon icon);
I haven't looked closely at the existing sidebar/symbols code yet, maybe it already provides such a function that could be used. It has also been mentioned that this could be done using the TagManager API. Plugins would walk their own internal ASTs or tag lists and build up the TM tag array, and Geany would use it for updating the symbols tree as it currently does (IIUC). I don't know much about TM so I can't really give an example callback for such an API.
Auto-Completion/Intellisense
This could be triggered at the exact same time in the same way it is now (and re-using the same preferences). It could call a callback function in the ft-plugins like:
gboolean (*complete_at)(GeanyPlugin *, GeanyDocument *, guint position, const gchar *partial_word, GPtrArray completion_list /* out */, gpointer user_data);
The `completion_list` would be filled in with whatever the provider thinks could be completed at `position`. It could be made more advanced in the future like allowing plugins to give icons, argument lists, documentation comment text, etc. For now it could just give strings to directly populate Scintilla's auto-complete listbox.
Calltips
To provide calltips, a provider could be called into like:
gboolean (*provide_calltips)(GeanyPlugin*, GeanyDocument*, guint position, const gchar *symbol, GPtrArray *overloads /* out */, gpointer user_data);
The `overloads` array would populated by the provider with the various overloads for the given `symbol` (function). As with auto-completion, at first this could just be a list of overloads represented as strings which directly populate Scintilla's calltip infos. This could be enhanced in the future to provide documentation comment text and placeholder insertion points into the editor in the future, but for now should be kept simple (see GtkSourceView, XCode, etc).
Go To Declaration/Definition
This could be either single callback passing a parameter to tell whether declaration or definition, or two separate callbacks. An example of the callbacks could be:
struct SourceLocation { gchar *filename; guint position; }; gboolean (*get_declaration_location)(GeanyPlugin*, GeanyDocument*, guint position, const gchar *symbol, GPtrArray *results, gpointer user_data);
and likewise for `get_definition_location`. The `results` array could be populated with `SourceLocation`s for each possible definition/declaration. For example there might be multiple declarations in different `#if` blocks you could jump to, for C-like languages. Geany already provides a UI popup list to pick where to jump, this should be re-used.
Build/Run Support
I haven't thought much on this yet, but in general there should be a way for ft-plugins to get called into when a the build/run features are activated.
Diagnostics
I also haven't thought much on this yet. It needs to be possible for ft-plugins, after getting notified of build/run events, to be able to update diagnostics information.
Some of the diagnostics display might include:
- Scintilla marker margin icons, indicating the type of diagnostic info
present for each line (could be more than one per line).
- Scintilla indicators (little coloured squigglies) showing the specific
range(s) of code where the diagnostics apply.
- Scintilla annotations giving further details on request.
- Tooltip messages when hovering over the marker margins or squigglied
text giving further details.
- Putting lines of diagnostics info in the msgwin compiler tab (already
supported to some extent IIUC).
Refactoring
This is just an idea that is probably long in the future, but ft-plugins could provide some common re-factorings (ex. rename, generate definition code, etc). I haven't thought on this much at all yet.
Almost surely I have left some out. What do you think?
Cheers, Matthew Brush _______________________________________________ Devel mailing list Devel@lists.geany.org https://lists.geany.org/cgi-bin/mailman/listinfo/devel
Hi Matthew,
sounds good. This is much more lightweight than how #1195 and various other discussions sounded, I'm happy :-).
All the described functions look good to me in principle except the sidebar symbol tree one. The current code is quite complex (I was fixing some minor issues there and spent a lot of time thinking if it could be simplified but I don't think so). The problem is this: if a file is reparsed and you get new symbols, if you just cleared the tree and repopulated it with the new tags, the tree would jump to the beginning no matter where the scrollbar was before. So what the code does now is it compares the old and new tags, removes the tags that aren't present in the new tags array and inserts new tags which weren't present in the old tag array to the right position. If you have a look at the code, this isn't probably something you want to write in a plugin :-). So a plugin should provide the full list of new tags so the tree can do all this diffing and updating.
Which brings me to a question - do you plan to generate TMTag(s) and feed them to the tag manager instead of the ctags ones? It shouldn't be that hard and if you do this, you could have the sidebar symbols updated for free.
These fields in TMTag are unused, don't waste time filling them:
gboolean local; /**< Is the tag of local scope */ guint pointerOrder; char *inheritance; /**< Parent classes */ char access; /**< Access type (public/protected/private/etc.) */ char impl; /**< Implementation (e.g. virtual) */
Cheers,
Jiri