The new documentation vs. the old documentation

It has been quite some time now that the documentation has changed form. Yet I still find myself more comfortable using the old website whenever I can. And when I can’t, like in the documentation of libadwaita, I try to treasure as much as possible from what I read, just for not having to navigate through the website too much.

I will try to make a list here of all the features that for me constitute regressions, hoping to be constructive.

1. Paragraphs are often collapsed

If I visit the main page of the documentation of libadwaita, it is probably because I want to have an overview of the library. But paragraphs are collapsed, which makes the overview impossible unless I click nine times.

collapsed

2. Things are documented in separate pages

Pages have basically become summaries, because the actual content is documented in separate subpages. This is how the documentation of a function in the new version looks like:

This is how the old version would present the same thing:

This regression is not only for the eye. In the past, if I wanted to see which functions take, for instance, GtkGestureClick * as argument, I could just type Ctrl + F and then GtkGestureClick *, and I would have a fast answer.

3. The table of contents gives no information

The return type of functions has disappeared from the table of content. Now it looks like an anonymous list:

toc-new

Whereas before it would provide information about data types:

toc-old

Again, this regression is not only for the eye. In the past, if I wanted to see which functions return, for instance, GtkGestureClick *, I could just type Home to reach the beginning of the page, then Ctrl + F, and then GtkGestureClick *, and I would have a fast answer.

4. Data types are in general gone

Of course I can still find them if I go to the dedicated subpage, but no data types appear in the comprehensive page, again making overviews impossible, unless one memorizes things one by one as I have to do when I deal with libadwaita.

Solutions

I have no reasons to doubt the technical superiority and higher introspective powers of gi-docgen compared to GtkDoc. However after the data is collected and parsed, an HTML document must be generated in the end. And in this particular passage I find GtkDoc still way superior than gi-docgen.

My wish list then goes as follows:

  1. Never collapse page sections
  2. I have no idea if someone prefers to have to navigate through subpages all the time instead of finding everything ready simply using the keyboard, but if that is the case, a solution could be to enable gi-docgen to create two outputs, one in which the documentation of a particular module is collected in one single page, and the other one in which the documentation uses subpages. Personally I will not visit this second output.
  3. Restore data type information in the table of contents
  4. Restore data type information in figure #2

This is my feedback after quite some experience with both formats, the old and the new one. I hope it will be useful.

4 Likes

Thanks for the feedback.

That makes the pages impossibly long to visually parse.

No, this detail won’t change.

No, it makes the sidebar useless, and the index too long. The index is meant to be used as a quick way to get where you want, and a full C declaration is just visual noise.

The reason gi-docgen works they way it does is to provide stable links, and a full description of every symbol; the indices are meant to be used to quick navigation, and the pages are kept short to avoid the typical work vomit of various API references.

I understand that some people are happier with a different output; personally, after 20 years of gtk-doc, I don’t really want to ever have to use it ever again. It’s why I wrote gi-docgen to work the way it does.

You’re free to write your own documentation generator: after all, it’s all coming from the introspection data.

Hi Emmanuele, thank you for your answer.

It could be easily solved by having a switch somewhere that says “Show sections collapsed”. Being a static collection of html documents, memorizing the choice could rely on cookies, or, even better, the Web Storage API.

This I don’t get. Having and additional option available will not affect what already exists…

I find that data types are as important as the brief to understand quickly what a function does. If for whatever reason I am looking for a function that allocates a particular string and I see const char * as return value, I already know that function is not what I am looking for, without even having to read the brief. The utility becomes even bigger with data types that are rarely returned (e.g.: GdkDisplay *).

Of course, I thought that the current output is not the result of randomness, but a wanted outcome. I am also thankful to you for improving the free software tools available for documenting the code. In this second message I tried to make the two points of view coexist (that is what I consider constructive).

I don’t know exactly what you did not like about GtkDoc, whether it was the parsing part, or the HTML generation part. Personally, the only big thing I find missing in GtkDoc is the ability to use markdown documents as input (as far as I know), otherwise I consider it a great piece of software. As for gi-docgen, I assume it is even better than GtkDoc in introspection and modernity, but I never tried it for creating the documentation because I don’t feel comfortable with the HTML generated. I am aware, however, that if it remains unmantained I will probably run out of options.

I am also curious to hear the opinion of other developers about the new documentation from the reader’s point of view (I assume that from the maintainer’s point of vew gi-docgen is better).

1 Like

I share the same opinion, I prefer the GTK-Doc HTML output.

I’ve filed these two feature requests for gi-docgen:

Also, I’m officially the new maintainer of GTK-Doc, but I’m too busy with other projects already. Co-maintenance / peer-review for gtk-doc is the solution that I propose, we can discuss things there.

However, GLib is moving away from GTK-Doc and use gi-docgen only. Which is problematic for me. So my plan is to keep a copy of the GLib 2.78 gtk-docs, which is not ideal because GLib still evolves, there are sometimes new APIs etc (but I’ll be aware of deprecations thanks to the compiler).

Edit: BTW, there is also HotDoc, which is used by GStreamer if I recall correctly.

1 Like

But still this is useless for functions that allocate into an out parameter. IMO it was always confusing that GTK-Doc showed the return type but not any of the parameter types, I don’t see why the return types are so special here that they need to be shown but nothing else does.

If you want to search through all the types like this, there is already an easy way: click the “source” link and then search through the header file.

That is great! When you have time, could you please have a look at this merge request? If you do, please answer there and not here.

Well no. In theory if I see

void allocate_to_out (
	gchar ** string_goes_here
);

I should know that I can modify the buffer copied to my pointer, while if I see

void copy_address_of_const_buffer_to_out (
	const gchar ** string_goes_here
);

I should know that I can’t. However I don’t know how much GLib/GTK is compliant with this more sophisticated case. It is something that happens rarely anyway.

I have a clone of the libadwaita repository permanently on my laptop exactly for this reason. But if looking at the source files becomes more convenient than reading the documentation it is not really a success, is it?

I know that gi-docgen is a great piece of software. I just think that currently it runs at one quarter of its power.

I am not sure how this comment is related to anything, you don’t see any of that in the GTK-Doc index because it does not show the parameter types there. It only shows the return types.

And you don’t need to clone the repo, browsing through the headers in /usr/include is enough to see all the public types and signatures. The documentation is not supposed to replace the source files, both have their place.

It does in the same page, just not in the index, but in the place in which the function is documented (which is in the same page anyway). This is why I was complaining about the disappearance of data types in general, not just from the table of contents.

You are right, /usr/include/ is sufficient. Once I am there, from time to time I just like to have a look also at what the functions actually do, in case I have doubts, which is why I keep the clone.

Right, but what you were saying before is that you wanted to look through all the functions to find a certain type. Maybe I misunderstand but IMO you can’t do that easily by looking through the full page.

For me, I probably have always used the headers more than the documentation because text editors with ctags or LSP support can just jump to the header and quickly search the whole file.

You are an insider of GLib/GTK, so everything is clear for you. I can try to show you the perspective of a developer that approaches the library for the first time.

Imagine a certain tutorial says: “To obtain this particular effect, use function gtk_blablabla()”. The developer then goes to the documentation of gtk_blablabla() and finds out that it takes a GtkFooBar * object as one of its arguments. The developer then wonders how the heck he or she can get a GtkFooBar * object, which functions create it, and so on. Often the developer will be lucky, because there will be a gtk_foo_bar_new() function somewhere. But that is not always the case, because there are objects that are created by other objects, which the developer is only supposed to use, not create.

This is only the first example that came into mind. I can only confirm that from the perspective of someone who did not create the GLib/GTK code, and therefore has not everything clear by divine intervention, data types are a very useful tool for finding out about things.

1 Like

You couldn’t tell that in GTK-Doc either because the GtkFooBar * could be returned by any function, not just one that is grouped together in the same page. Also that is still pretty useless for libraries like GTK because in a lot of places it returns GtkWidget * for convenience instead of the actual type.

BTW I would not call myself an “insider”, this is an open source project so anyone can go read the code and see how it works. I probably have been developing GTK apps for longer than the average developer so I have a different opinion on things, but if you want to search the header files that works with any library, as long as you know how to use grep…

Very true. But with a cross-research it would take a very short time. If I remember correctly, the first time I encountered GdkMonitor * I had exactly this problem (it was still GTK3), which I solved by searching the GdkMonitor * string in two or three pages. It would have been probably harder without GtkDoc to find out that gdk_display_get_monitor_at_window() was the function I was looking for.

FYI, older GTK-Doc versions showed in the Functions section not only the return type but also all the parameters (for all the functions belonging to the html page). It was a small regression in my opinion, but we didn’t have the choice. The advantage is that there is now less scrolling to do, but before it was basically the equivalent of the header file (more or less).

1 Like

I guess I just don’t see why it is easier to look through random GTK-Doc pages until you find what you are looking for, instead of just using grep -r GdkMonitor /usr/include/gtk-4.0. The one thing this will miss is GObject signals, but using a “Functions” index will similarly skip those as well as struct members and function pointer types, etc.

For GLib and its table of contents (TOC) with GTK-Doc, I find it particularly important, since it’s a sizable library.

Example: the “GLib Data Types” chapter. When I write some code and I need to choose a data type, I look at that chapter and choose one that fits my needs (e.g. GList vs GSList vs GQueue).

With everything in alphabetical order, for the whole of GLib, we will lose that overview. The “GLib Data Types” will be mixed with " GLib Utilities" and the other categories.

Launching grep -r GdkMonitor /usr/include/gtk-4.0 would work too, but the output is ugly and you cannot click on things:

$ grep -r GdkMonitor /usr/include/gtk-4.0
/usr/include/gtk-4.0/gtk/gtkwindow.h:                                           GdkMonitor *monitor);
/usr/include/gtk-4.0/gdk/gdkdisplay.h:GdkMonitor * gdk_display_get_monitor_at_surface (GdkDisplay *display,
/usr/include/gtk-4.0/gdk/wayland/gdkwaylandmonitor.h:struct wl_output *gdk_wayland_monitor_get_wl_output       (GdkMonitor *monitor);
/usr/include/gtk-4.0/gdk/x11/gdkx11monitor.h:XID               gdk_x11_monitor_get_output          (GdkMonitor *monitor);
/usr/include/gtk-4.0/gdk/x11/gdkx11monitor.h:void              gdk_x11_monitor_get_workarea        (GdkMonitor   *monitor,
/usr/include/gtk-4.0/gdk/x11/gdkx11display.h:GdkMonitor * gdk_x11_display_get_primary_monitor (GdkDisplay *display);
/usr/include/gtk-4.0/gdk/gdktoplevellayout.h:                                                            GdkMonitor        *monitor);
/usr/include/gtk-4.0/gdk/gdktoplevellayout.h:GdkMonitor *            gdk_toplevel_layout_get_fullscreen_monitor (GdkToplevelLayout *layout);
/usr/include/gtk-4.0/gdk/gdkmonitor.h:#define GDK_MONITOR(object)        (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MONITOR, GdkMonitor))
/usr/include/gtk-4.0/gdk/gdkmonitor.h:typedef struct _GdkMonitor      GdkMonitor;
/usr/include/gtk-4.0/gdk/gdkmonitor.h:typedef struct _GdkMonitorClass GdkMonitorClass;
/usr/include/gtk-4.0/gdk/gdkmonitor.h:GdkDisplay  *     gdk_monitor_get_display         (GdkMonitor   *monitor);
/usr/include/gtk-4.0/gdk/gdkmonitor.h:void              gdk_monitor_get_geometry        (GdkMonitor   *monitor,
/usr/include/gtk-4.0/gdk/gdkmonitor.h:int               gdk_monitor_get_width_mm        (GdkMonitor   *monitor);
/usr/include/gtk-4.0/gdk/gdkmonitor.h:int               gdk_monitor_get_height_mm       (GdkMonitor   *monitor);
/usr/include/gtk-4.0/gdk/gdkmonitor.h:const char *      gdk_monitor_get_manufacturer    (GdkMonitor   *monitor);
/usr/include/gtk-4.0/gdk/gdkmonitor.h:const char *      gdk_monitor_get_model           (GdkMonitor   *monitor);
/usr/include/gtk-4.0/gdk/gdkmonitor.h:const char *      gdk_monitor_get_connector       (GdkMonitor   *monitor);
/usr/include/gtk-4.0/gdk/gdkmonitor.h:int               gdk_monitor_get_scale_factor    (GdkMonitor   *monitor);
/usr/include/gtk-4.0/gdk/gdkmonitor.h:int               gdk_monitor_get_refresh_rate    (GdkMonitor   *monitor);
/usr/include/gtk-4.0/gdk/gdkmonitor.h:GdkSubpixelLayout gdk_monitor_get_subpixel_layout (GdkMonitor   *monitor);
/usr/include/gtk-4.0/gdk/gdkmonitor.h:gboolean          gdk_monitor_is_valid            (GdkMonitor   *monitor);
/usr/include/gtk-4.0/gdk/gdkmonitor.h:const char *      gdk_monitor_get_description     (GdkMonitor   *monitor);
/usr/include/gtk-4.0/gdk/gdkmonitor.h:G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkMonitor, g_object_unref)

Clicking on things is one of the purposes of a documentation after all, isn’t it?

Right, so to me that just means there should be an overview page on the glib docs with comparisons of the data types to help users choose. Possibly some tables can be added to compare the performance characteristics. See for example how this is done in the .NET or Rust documentation.

But you also cannot easily click on things when you have to navigate through many pages just to find what you are looking for. Maybe the gi-docgen search should gain the ability to search for type parameters? My point here is that the any search or indexing features need to be better than grep to consider adding them.

Edit: Also, if you have LSP in your text editor and you have it indexing the source of the library then you can actually click on everything including the documentation, and you can search through all symbols in a way that is clickable too.

Definitely that would be great. But it would also be interesting to hear why according to you they cannot appear also in the TOC and the brief. If it is only a matter of space, it is possible to write them very small, like in this mockup:

small-data-type

The open all/collapse all button is an option, and mainly needs somebody implementing it.

Why would I add something that completely undoes the design of the output? What incentives exist that would make me care about something that I wouldn’t test, use, or care for? Because it would make madmurphy happy? You are but one consumer of the API reference.

If you want a documentation generator that parses GIR data and turns it into a C API reference, write your own, instead of telling me to add an option.

Of course. Writing here was also a way to understand if I am alone in feeling uncomfortable about transforming pages into summaries of subpages, or in general if I am alone in preferring big single-page documentations to split ones. If I am, then I suppose I am indeed but one consumer of the API reference.

However I have touched several points. While I might be alone in some of them, I might not be in others.