After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 773351 - Send a signal when applying a GtkSourceStyle to a GtkTextTag
Send a signal when applying a GtkSourceStyle to a GtkTextTag
Status: RESOLVED WONTFIX
Product: gtksourceview
Classification: Platform
Component: General
unspecified
Other All
: Normal enhancement
: ---
Assigned To: GTK Sourceview maintainers
GTK Sourceview maintainers
Depends on:
Blocks:
 
 
Reported: 2016-10-22 13:04 UTC by Sébastien Wilmet
Modified: 2018-05-26 13:58 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Sébastien Wilmet 2016-10-22 13:04:13 UTC
Send a signal when applying a GtkSourceStyle to a GtkTextTag, to be able to apply other GtkTextTag properties.

See https://bugzilla.gnome.org/show_bug.cgi?id=762533#c4 and further comments.

GtkSourceBuffer is maybe a good class to add the signal/vfunc.
Comment 1 Sébastien Wilmet 2016-10-22 18:33:58 UTC
The use-case at bug #762533 is to set the GtkTextTag:left-margin property to the Markdown headings.

For headings, def.lang has already different styles: heading0 to heading6. markdown.lang should apply those styles (please open a separate bug for that).

In a *.lang file, there are style elements like this:
> <style id="chapter" _name="Chapter Heading" map-to="def:heading1"/>

There can be a chain of map-to's. A "final style" is a <style> at the end of the map-to chain, i.e. a style that doesn't contain a map-to attribute. The 'def:heading1' is a "final style"; 'chapter' isn't.

A GtkSourceStyleScheme doesn't necessarily provide a GtkSourceStyle for each style ID.

So a possible solution is to add a signal in GtkSourceBuffer, with the following parameters: GtkSourceBuffer, GtkSourceStyleScheme, the "final style" ID and the GtkTextTag.

The GtkSourceStyle can be retrieved from the GtkSourceStyleScheme, but can be NULL. The signal would also be emitted in that case.

The final_style_id can be NULL, to unapply the style from the tag. Like gtk_source_style_apply().

If the signal/vfunc is added (with a corresponding function in GtkSourceBuffer to send the signal), then gtk_source_style_apply() will probably need to be deprecated (it would no longer be useful in external code, it should be made private again).
Comment 2 Sébastien Wilmet 2016-10-22 19:54:08 UTC
The style IDs of a *.lang file are exposed in the API:
gtk_source_language_get_style_ids()
gtk_source_language_get_style_fallback()

get_style_fallback() returns the map-to.

Also, a StyleScheme can define a style for a specific language, for example classic.xml defines a style for latex:display-math, although latex:display-math has a map-to to def:string.

So the signal should maybe send the original style_id, not the final one.
Comment 3 Everaldo Canuto 2016-10-22 20:52:42 UTC
GtkTextTagTable ::tag_added is also working nice using class name with prefix "gtksourceview:context-classes:".
Comment 4 Sébastien Wilmet 2016-10-23 07:59:26 UTC
Yes, but you need to add context classes specifically for that. If we stretch that idea further, it is also possible to add a different context class in each <context> of a *.lang, to be able to navigate through the syntax tree. But AFAIK, the context classes were not designed for that (and there can be performance problems, I don't know).

Another way to solve your use-case is with bug #762623, but the problem is that you would need to modify the style schemes. Taking a random style scheme from the internet won't work, your application needs to ship modified style schemes.

There is also a plan to support CSS for style schemes. So applications could add some CSS to customize certain styles. But GtkTextTag doesn't support CSS.

Adding a signal is a simpler solution, and better fits your use-case: you want to set additional GtkTextTag properties for certain style_ids of a certain GtkSourceLanguage.
Comment 5 Sébastien Wilmet 2016-10-23 08:09:06 UTC
So maybe a better place to add the signal is to GtkSourceLanguage.
Comment 6 Sébastien Wilmet 2016-10-23 09:32:22 UTC
To explain why adding context-classes is not an ideal solution for the use-case here: the purpose of a context-class is to know where it is located in the buffer, i.e. where the tag is applied. It is not for styling purposes. For styling purposes (what you want to do), a *.lang file contains <style> elements that a <context> can refer to with the style-ref attribute. The <style> elements of a *.lang file are then styled with a style scheme. The problem is that the style scheme system is not flexible enough and cannot be extended. Hence the need to add a signal, or solving bug #762623 or adding CSS support. I think the signal is the easiest (clean and upstream) solution, at least for your use-case.

For a less clean solution, you can indeed modify the markdown.lang in your application (downstream), and adding the context-classes. But if markdown.lang is improved upstream, your application will not automatically benefit from it.
Comment 7 Sébastien Wilmet 2016-10-23 10:20:53 UTC
And to explain why I don't like setting a name to a GtkTextTag corresponding to a certain <style> element of a *.lang file:

1. A tag name is not a nice API, the application needs to listen to the GtkTextTagTable::tag-added and tag-removed signals. For context-classes, the recommended API is the API provided by GtkSourceBuffer: gtk_source_buffer_iter_has_context_class() etc.

2. With a GtkTextTag name for <style> elements, the application can know where the tag is applied in the buffer. <style> elements, as explained in Comment 6, are more for styling purposes, while context-classes are more for knowing where they are applied in the buffer. So API-wise, it is better to keep <style> elements for what they are designed for: styling purposes (which means: setting GtkTextTag properties, basically).

What GtkSourceView could provide is an API to navigate through the syntax tree. I.e. knowing where each <context> is applied to the buffer, navigating to the children, the parent, etc. But it is quite complex. Anyway, navigating through the syntax tree must be done wrt <context> elements, not <style> elements.

3. I know very little about the ContextEngine implementation. I don't know if it is a good idea to set a name to <style> tags. Maybe in certain situations several tags are created for the same <style>, so if we set the same name there can be a conflict. Think about PHP that can highlight embedded HTML/JS, etc. I don't really know how it is implemented.
Comment 8 Everaldo Canuto 2016-10-23 12:25:07 UTC
(In reply to Sébastien Wilmet from comment #7)
> And to explain why I don't like setting a name to a GtkTextTag corresponding
> to a certain <style> element of a *.lang file:
> 
> 1. A tag name is not a nice API, the application needs to listen to the
> GtkTextTagTable::tag-added and tag-removed signals. For context-classes, the
> recommended API is the API provided by GtkSourceBuffer:
> gtk_source_buffer_iter_has_context_class() etc.

It works with GtkTextTagTable::tad-added using tag parameter but I agree that it is not the best solution (I will keep using it as a workaround). In case of using GtkSourceBuffer, the problem is that I need to create a new GtkTextTag and keep tracking of it to prevent recreate it unless we implement this new signal. In any case, theres other problem that I will describe below.
 
> 3. I know very little about the ContextEngine implementation. I don't know
> if it is a good idea to set a name to <style> tags. Maybe in certain
> situations several tags are created for the same <style>, so if we set the
> same name there can be a conflict. Think about PHP that can highlight
> embedded HTML/JS, etc. I don't really know how it is implemented.

Well, I don't see names as problem because even if id is the same, the lang is different. For html comment, tagname will be "html:comment" and for js it will be "js:comment" but like a context class workaround, theres a problem.

Using left-margin works here until I change font sizes, thats because I need to calculate the size of "#" and " " (space) to create my "negative" margin. Right now, I have a default margin of 200 for GtkSourceView and them I change GtkTags like this left-margin = default-margin - size-of-space - (size-of-sharp * heading-level).

Since GtkTextTagTable::tag-added or even GtkSourceBuffer::highlight-updated aren't triggered again after change font or font-size, the format looks weird. 

Did you suggest any solution for that? I was thinking about a new GtkSourceStyle but it will not solve the problem since margins and indent are pixel based.
Comment 9 Sébastien Wilmet 2016-10-23 12:59:37 UTC
That's why it is important to explain in details your use-case. Otherwise we make wrong assumptions about what you need.

The signal is thus not a good solution for you.

But what you want to achieve is quite advanced. It is normal that GtkSourceView doesn't handle such use-cases. But the GtkTextView API is still there, you can create and apply your own tags. And for a Markdown editor, you'd anyway be better off having your AST (based on the GtkTextBuffer, using a GtkSourceRegion). The syntax highlighting engine of GtkSourceView is great for syntax highlighting, but is not suitable for accessing the AST from an application.

As a quick solution, you can use context-classes.
Comment 10 Sébastien Wilmet 2018-05-26 13:58:57 UTC
It's unlikely that this feature is ever going to be implemented, so I close the bug.