GtkSourceView with a custom highlighting engine for a custom language

I want to use GtkSourceView with my custom syntax parser to highlight syntax of a custom markup language while supported languages should be parsed by GtkSourceView as usual. I prefer that my custom markup can use the GtkSourceView’s existing switchable themes/styles.

My custom syntax parser generates following parsing events upon buffer processing:

{"startpos":0,"endpos":0,"annot":"blankline"}
{"startpos":5,"endpos":5,"annot":"+heading"}
{"startpos":7,"endpos":20,"annot":"str"}
{"startpos":21,"endpos":21,"annot":"-heading"}
{"startpos":26,"endpos":26,"annot":"blankline"}
{"startpos":31,"endpos":31,"annot":"+para"}
{"startpos":31,"endpos":31,"annot":"+emph"}
{"startpos":32,"endpos":42,"annot":"str"}
{"startpos":43,"endpos":43,"annot":"-emph"}
...

They are convenient to mark certain chunks of the GtkSourceView’s TextBuffer based on the positions as needed.

  1. Which entry point into the GtkSourceView code would you suggest to accomplish this task?
  2. Do you have any other useful advises on this?

Maybe @chergert knows?
Thank you!

There are several reasons why I need to use a custom syntax parser rather than adding a new language definition to GtkSourceView. One of them - GtkSourceView’s parser has some limitations that do not allow my syntax to get recognized.

So what I’m actually asking about is the following:

Let’s assume I have this string in GtkSourceView buffer: This is a *bold* word. How should I mark *bold* so that it is displayed bold and once I change themes (as is currently possible in the Gnome Text Editor) - it’s style will be changed according to the theme (but remain bold of course)?..

Thank you!

Hi,

It’s possible, but as it will conflict with the GtkSourceView own parser, you’ll have first to disable GtkSource.Buffer:highlight-syntax.

Then you’ll have to create one GtkTextTag per “annot” kind, and map it to a style:

tag = buffer.create_tag()
style = buffer.get_style_scheme().get_style("def:string")
style.apply(tag)

And store the tag in a hash table {annot → tag} for later reuse.

Then, for each entry of your syntax parser, apply the tag to the text chunk:

tag = [get the tag for annot]
ibeg = buffer.get_iter_at_offset(startpos)
iend = buffer.get_iter_at_offset(endpos)
buffer.apply_tag(tag, ibeg, iend)
1 Like

Thank you very much for your response!

It took me some time to translate your code into C. Here is what I came up with:

  gtk_source_buffer_set_highlight_syntax (source_buffer, false);
  tag_bold = gtk_source_buffer_create_source_tag (source_buffer, "bold", NULL);
  style = gtk_source_style_scheme_get_style (gtk_source_buffer_get_style_scheme (source_buffer), "def:strong-emphasis");
  gtk_source_style_apply (style, tag_bold);
  gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER(source_buffer), &ibeg, 10);
  gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER(source_buffer), &iend, 18);
  gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER(source_buffer), tag_bold, &ibeg, &iend);

  manager = gtk_source_style_scheme_manager_get_default ();
  scheme = gtk_source_style_scheme_manager_get_scheme (manager, "cobalt-light");
  const gchar * const *schemes;
  schemes = gtk_source_style_scheme_manager_get_scheme_ids (manager);

  for (int i = 0; schemes[i] != NULL; i++)
    g_print ("%s\n", schemes[i]);


  if (scheme)
    gtk_source_buffer_set_style_scheme (source_buffer, scheme);

  gtk_box_append (GTK_BOX (box), sourceView);

The problem is - changing the theme doesn’t seem to change the theme of the text while it does change the background color. Here how 2 different theme look like in my window:

and

While the same text with the same two themes in Gnome Text Editor looks like this:

image

and

image

As you can see in the latter both background and the text are displayed differently.

What am I doing wrong?

Thank you!

Yes, you’ve to update your tags when the style scheme changes.

(sorry, it’s Python-like code again):

buffer.connect("notify::style-scheme", on_style_scheme_change)

Then from the callback, call again:

  style = gtk_source_style_scheme_get_style (gtk_source_buffer_get_style_scheme (source_buffer), "def:strong-emphasis");
  gtk_source_style_apply (style, tag_bold);

No need to rebuild the tags list, just update the tags to the new style.

1 Like

Note that gnome-text-editor default style is Adwaita (where “def:strong-emphasis” is black and italic) while the gtksourceview default style is Classic (where “def:strong-emphasis” is brown).

That’s why the initial style looks different, and will stay so until the tags are updated to the new one.

1 Like

Thank you very much - it worked!

Now the last thing that remained is this: “Then you’ll have to create one GtkTextTag per “annot” kind, and map it to a style”. Since I’m new to GTK and GLib (should I use it?) - can you, please, suggest the best way to implement this map, giving 2-3 example map items… Preferably in C…

In C, I would recommend using GLib’s GHashTable:

Probably this constructor will be the most suitable for a string -> texttag mapping:

g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref)

(replace g_free by NULL if you insert constant strings as keys)

Then use the insert() and lookup() methods.

Look for language_ids in gtksourceview/gtksourcelanguagemanager.c · master · GNOME / gtksourceview · GitLab for a simple example.

1 Like