Back to GNOME development

After writing my last blog post – a retrospection about my first 10 years of Free Software development – it made me want to contribute to GNOME again. I didn’t contribute much this past year (in short, too much stress). But I’m back, I hope my keen interest will continue.

I’ve restarted with gedit. I’m improving the documentation for contributors, I’ve written a new roadmap, and done the 3.33.92 development release. Plus already a small yak shaving in jhbuild (doing the release) for the gedit contributors’ docs 🙂

Thoughts on the Linux Mint X-Apps forks

You may be aware that Linux Mint has forked several GNOME applications, either directly from GNOME (Totem -> Xplayer, Evince -> Xreader, Eye of GNOME -> Xviewer), or indirectly via MATE (gedit -> pluma -> XEd).

GNOME is like the Debian of the Linux desktops. But is it a good thing? In the current state of the code, I don’t think so and I’ll explain why, with a solution: creating more shared libraries.

At the end of the day, it’s just a matter of design and usability concerns. We can safely say that the main reason behind the forks is that the Linux Mint developers don’t like the new design of GNOME applications with a GtkHeaderBar.

And there are perfectly valid reasons to not like headerbars. For gedit for example, see the list of usability regressions at this wiki page.

Currently the trend is GtkHeaderBar, but what will it be in 5 years, 10 years? Let’s face it, GNOME is here just following the new trend that came with smartphones and tablets.

So, a GNOME application developer needs to know that:

  • A GUI is an ever-changing thing, exactly like the clothes that you bought last year are already obsolete, right?
  • When the GUI changes too much, other developers don’t like it and fork the project. For valid reasons or not, this doesn’t matter.

The four X-Apps forks account for roughly 200k lines of code. In the short-term it works, Linux Mint has apps with a traditional UI. But hey, porting the code to GTK+ 4 will be another beast, because the four X-Apps still use the deprecated GtkUIManager and GtkAction APIs, among other things.

But when we look at the codebase, there are a lot of code that could be shared between a GNOME app and its fork(s). So there is a solution: creating more shared libraries. The shared libraries would contain the backend code, of course, but also some basic blocks for the UI. The application would just need to glue things up together, assembling objects, binding GObject properties to GSettings, create the main GtkWindow and a few other things.

The difference would be that instead of forking 200k lines of code, it would be forking maybe 20k lines, which is more manageable to maintain in the long term.

In the case of gedit, making its code more re-usable is exactly what I do since several years, but for another reason: being able to create easily specialized text editors or small IDEs.

Beside avoiding code duplication, creating a shared library has the nice side effect that it is much better documented (usually), and with an API browser like Devhelp, it’s a breeze to discover and understand a new codebase, it permits to have a nice overview of the classes. It’s of course possible to have such documentation for application code, but in practice few developers do that, although it would be a big step towards lowering the barrier to entry for newcomers.

When untangling some code from an application and putting it in a shared library, it is also easier to make the code unit testable (and unit tested!), or at least write a mini interactive test in case of frontend code. Making the code more stable, getting closer to bug-free code and thus more successful software.

Developing a shared library doesn’t necessarily mean to provide backward compatibility during 10 years. Nothing prevents you from bumping the major version of the library every 6 months if needed, making the new version parallel-installable with the previous major versions. So that applications are not forced to update the code when there is an API break.

But creating a library is more difficult, API design is hard. But in my opinion it is worth it. GNOME is not only a desktop environment with an application suite, it is also a development platform.

gspell news

  • gspell is now fully hosted on gnome.org!
  • There is now a mailing list.
  • In addition to LaTeXila, gspell is now also used by gedit (5,800 lines removed, yay!).
  • The 0.1.x version has branched and is meant to be installed alongside GNOME 3.18.
  • If everything goes fine, the 1.0 version will be released at the same time as GNOME 3.20, with a stable API.

API reviews are more than welcome!

Stay tuned.

Announcing gCSVedit, a simple text editor to edit CSV files

As part of my job at the Université Catholique de Louvain, one of my projects is to develop gCSVedit, a small and simple text editor to edit CSV/TSV files.

gCSVedit is now a free/libre software (GPLv3+ license) and is hosted on GitHub.

Other delimiter-separated values (DSV) files are supported, not just comma-separated values (CSV) files, but “CSV” is more commonly used to refer to that kind of file.

Screenshot of gCSVedit
gCSVedit with the columns aligned. Note also the gray bullets to represent the spaces present in the file.

Why developing a new application for editing CSV files?

CSV files can already be opened in a spreadsheet software like LibreOffice Calc and Gnumeric. But it’s not really user-friendly. Just to open the file you need to provide tons of options:

Screenshot of opening a CSV file with LibreOffice Calc
Opening a CSV file with LibreOffice Calc

A general-purpose text editor like gedit is not the best choice either, because the columns are not aligned. There are some plugins for Eclipse or other IDEs available, but launching and using a complete IDE just to view or edit a CSV file is not user-friendly either.

The best is a specialized application, to do just one thing but do it well. With a user interface that goes straight to the point.

Spreadsheet or text editor?

With a text editor, all characters are visible, including the delimiters. We have thus a greater control. When writing a script to extract the data contained in the file, it’s important to view every character in case of problems (like an extra separator in the data but not for the column titles).

Also, some software that generate CSV files sometimes also include an header, i.e. some text before the actual CSV fields. With a text editor, the header can be shown in a natural way.

Future plans

Create an xdg-app for GNU/Linux. And implement more features of course!

Hopefully in the future it’ll be possible to re-use more code of gedit, to have a decent text editor (although gCSVedit is already completely usable).

So, nothing revolutionary here, it’s a small project. But I think it can bring a better usability. Comments, questions?

PS: to show where are the real spaces (those present in the file, not those added for the alignment), I’ve already contributed to GtkSourceView and GTK+. There will maybe be more contributions in the future, for example to implement a utility to insert virtual spaces, i.e. the text editor should behave as if the added spaces didn’t exist. Or, finally implement rectangular selection in GtkTextView.

Edit: gCSVedit has moved several times where it was hosted, I’ve updated the above URLs.

Introducing gspell, a new spell checking library

As part of the LaTeXila project I’m working on a new spell checking library called gspell.

Some background

At first I wanted to contribute to GtkSpell so that GtkSpell and GtkSourceView work well together, without a dependency on each other. GtkSourceView defines a no-spell-check region. For LaTeX, the region includes the LaTeX command’s names, for example. But GtkSpell didn’t read that region, and the region was available only through the GtkSourceView API. Adding a dependency on GtkSourceView in GtkSpell was not desirable, because many applications use GtkSpell only. Also, a library like GtkSpell could potentially add the support for GtkEntry too, so if there is a dependency on GtkSourceView, it isn’t nice for an application that wants only the spell checking for a GtkEntry. The solution was actually really simple: the no-spell-check region is a GtkTextTag. After setting a name to the tag and expose it in the API, it was possible for GtkSpell to lookup the tag and read the region.

So the patches for GtkSourceView and GtkSpell have been merged, to remark only later that there was a quite annoying text responsiveness problem on long lines (e.g. a wrapped line that takes 5 lines on the screen). And… there was exactly the same problem with the gedit spell plugin. The typed text appeared with a noticeable delay. Fixing that problem was more complicated. The text needs to be spell checked after a timeout. But adding a timeout function means that the remaining region to spell check needs to be tracked, which was not the case, neither in GtkSpell nor in gedit. And another problem is that GtkSpell anyway needed some code clean-ups. On the other hand the gedit code was in a slightly better shape and, more importantly, it had more features. For example gedit has a dialog window to spell check an entire document, one (misspelled) word at a time, whereas GtkSpell only has an “in-line” checker. An in-line checker is not convenient in the case of a very long document with very few misspelled words, in that case the dialog window is more convenient (btw it could also be an horizontal bar above or below the text, to not hide the text by the dialog window).

So, since the gedit spell plugin’s code had more features, I’ve decided to improve that code base instead. The gedit plugin code also needed some code clean-ups, but at least the code architecture was for the most part good. After those code refactorings and bug fixes, it was easier to fix the responsiveness problem. Then, after some more “spell shaking” (haha) the code was re-usable for other text editors.

Enters gspell

The gedit spell plugin’s code has then been copied into its own repository, called gspell. The library is still under construction, but I hope to get a first version available when GNOME 3.18.0 is released (September 21, according to the schedule). That first version will not have a guaranteed stable API, be warned! It is currently available on my GitHub account, but if things go well, I’ll ask during the next development cycle to get it hosted on gnome.org!

Update: gspell is now hosted on gnome.org, the links above have been updated. The project page is now at https://wiki.gnome.org/Projects/gspell.

What it means for LaTeXila

Basically, the LaTeX command’s names won’t be highlighted anymore with a red wavy underline. And there will be a dialog window to spell check an entire file. Also, on the LaTeXila side, settings will be stored on a file-by-file basis (to remember the language and whether the in-line checker is activated), and there will be settings in the preferences dialog for the default configuration.

I already have a branch in LaTeXila that uses gspell, and it works pretty well. There is still a bit of work to do, but it should be ready soon. Since it would be a pity to not have it for LaTeXila 3.18, I’ll delay the release of LaTeXila 3.18.0 for a few weeks to let translators have the time to update the translations.

File loading and saving in GtkSourceView, finally

Last year GtkSourceView saw a new search and replace API. This year it’s the file loading and saving that has just landed! It is in the continuity of making the gedit source code more reusable for other text editors.

In short, the back-end part of the file loading and saving in gedit has been moved to GtkSourceView, with a new and more flexible API to better wrap the feature. The code has been modified to follow GIO conventions for asynchronous operations, to use GTask internally, and replace the uses of GSettings by properties, among other things.

The file loader auto-detects encodings, newline types and compression type (yes gedit can open gzip files). Invalid characters can also be displayed with their corresponding hexadecimal value, because GtkTextBuffer accepts only valid UTF-8 text. And progress information is reported during the operation.

The API is stateful: the file parameters (encoding etc) are remembered between a file loading and a file saving in a GtkSourceFile object. Unfortunately the new API is still quite low-level. The application must configure the file loader and the file saver, and some errors are returned to the application.

So the front-end and errors handling is still implemented in gedit. Errors and progress information are displayed in an info bar, above the GtkSourceView widget. For some errors, gedit proposes different actions to the user, like choosing another encoding.

API design

If you are a text editor developer, don’t hesitate to have a look at the GtkSourceFile API. The API can still change during this 3.13 development cycle. The notes about the API design are available on bugzilla (there has been four iterations). Here is a summary.

The API is a bit heavy, with the following classes: GtkSourceEncoding, GtkSourceFile, GtkSourceFileLoader and GtkSourceFileSaver. There are good reasons for having two class’ names derived from a verb (“to load” and “to save”), which is generally a hint that those classes should be replaced by a method (i.e. an action). The reasons are partly similar with the new GSubprocessLauncher in GIO: the FileLoader and FileSaver classes are there not only for launching the operation, but also for configuring it with a nicer and more extensible API than one function with a dozen parameters. With the FileLoader and FileSaver, we can add properties, functions and even signals. And the FileLoader and FileSaver classes are quite useful in gedit: when an error occurs and the user clicks on a button in the info bar, the loader or saver object is reconfigured and the operation is relaunched, without the need to keep the initial configuration around. Also, the FileLoader or FileSaver properties are applied to the GtkSourceFile object only on a successful operation, so the GtkSourceFile state is (normally) consistent with the underlying file on the disk, at least at the time of the last load or save done with GtkSourceView.

Possible follow-ups work

A possible follow-up is to make the front-end code more reusable, either by creating higher-level classes in GtkSourceView, or by creating a git submodule, like the libgd (without API stability guarantees in the latter case).

Another possible follow-up is to analyze and improve the performances, which are currently quite bad. For short files it is not visible of course, but opening a very big log file takes more time than with other popular text editors.

There are other possible improvements, like unescaping invalid characters when saving, or avoid blocking the GtkTextBuffer when (auto-)saving a short remote file on a slow network connection.

Changes for gedit plugins

Unfortunately there are some changes in the gedit API for plugins, mainly in GeditDocument. Fortunately the changes are well documented, and most plugins should still work without any modification.

Conclusion

The file loading and saving can quickly become a fairly complex beast. Now this code is available for other GTK+ text editors.

Thanks to Paolo Borelli for the reviews!

TL;DR:

  • In GtkSourceView: 29 files changed, 7909 insertions(+), 3 deletions(-)
  • In gedit: 49 files changed, 1888 insertions(+), 8819 deletions(-)
  • In gedit-plugins: 11 files changed, 22 insertions(+), 31 deletions(-)

This is a 12% code increase in GtkSourceView, and a 6% code decrease in gedit.

PS: As usual, some tests would be more than welcome before the stable version in September.

Making the gedit source code more reusable

On IRC I see some developers working on other text editors based on GtkTextView/GtkSourceView. It is a good thing in my opinion to have specialized text editors. They are easier to use and configure. A specialized application has a potentially better usability. A general-purpose text editor like gedit is of course still needed for languages not covered by a specialized text editor or IDE.

The problem is that creating a new text editor based on GtkSourceView is still quite a lot of work. Instead of reinventing the wheel, the idea is to make the gedit source code more reusable by moving it to GtkSourceView or to a git submodule. This wiki page has all the details, it keeps track of the progress made (see also the RoadMap), more details on the “why?”, and a paragraph on Anjuta.

This blog post was to make developers aware of this initiative. If you are interested, join us on the #gedit channel or the mailing list!

The GSoC on GtkSourceView/gedit comes to an end

A small update on my GSoC.

The first part took a little longer than expected. But I’m happy with the results, the search and replace API is simple and flexible, there were not a lot of bugs to fix, and gedit users will be happy with the improvements (including the regex search).

I’ve changed a little what was initially planned for the second part of the GSoC. Ideally, it was to rework the color schemes to use CSS, and investigate GtkTextTag to modernize it. For the color schemes, it was not really a high-priority issue for GtkSourceView, writing them in XML works fine. And the GtkTextTag investigation would have been the logical follow-up. But with the remaining time, I have found other interesting and smaller tasks instead.

The past few weeks I worked on various things in other parts of GtkSourceView and gedit: better document the API, fix some bugs, improve the code here and there, and investigate two longer projects: the code folding and making the gedit source code more reusable.

I’ve written a utility class to navigate quickly through a set of GtkTextMarks. It is a cleaner implementation of GtkSourceMarks, and it will be useful for the code folding.

Making the gedit source code more reusable

For making the gedit source code more reusable, I’ve created a git submodule called libgedit. Like the libgd, the API/ABI stability is not guaranteed. The purpose is to try to move as most code as possible in the libgedit, iterate the API if needed until it is good enough to be included in GtkSourceView. So the libgedit would be a staging area between gedit and GtkSourceView. There is a problem though: gedit has an API for its plugins. And if possible, it’s better to not break the plugins… If the code moves from gedit to the libgedit, and then from the libgedit to GtkSourceView, there can be several API breaks. On the other hand, if the code goes directly in GtkSourceView, there is at most one API break (that can be avoided if the gedit functions are simply deprecated, not removed). With the second solution, the risk is to discover problems too late.

Maintaining the gedit plugins API in the libgedit is one problem. There are other problems: it would be nice to share the translations; have an API documentation only for the libgedit (with GTK-Doc, I mean); working with a git submodule is less convenient; having the same namespace (“Gedit”) for gedit and libgedit is a problem when trying to make the code more reusable; a headers nightmare, some headers are private, others are public, and others are split between gedit and libgedit; and so on.

So I think it will be simpler to move the code directly to GtkSourceView. The API must be well thought. The developers must have enough time during the 6-months development cycle to iterate the API if needed. And ideally the API must be tested on other applications than gedit. If it is done slowly but surely, by small steps every cycle, it should be doable.

That’s all folks. Thanks to Ignacio Casal Quinteiro (nacho) and Paolo Borelli (pbor) for their reviews, advices and (sometimes late 😉 ) testing. Thanks to Garrett Regier (gregier) for having well tested the new search and replace in gedit. And thanks to Google and GNOME, for accepting me as a GSoC student.

Regex search in gedit and GtkSourceView, finally

Regex search in gedit
Regex search in gedit

Although regular expression searches were possible with plugins, it is now available by default in gedit. The search and replace works too, and you can use backreferences (\0, \1, …) in the replacement text.

All this work has been merged upstream, just in time before the freeze.

Reworked search and replace API in GtkSourceView

Behind the scene, the regex search is implemented in GtkSourceView. For most cases, it scales well for big text buffers, since multi-segment matching is done: when a partial match is returned, we take a bigger segment. Read the lengthy implementation overview at the top of gtksourcesearchcontext.c for more details.

Besides the regex search, the API is now more flexible. Roughly speaking, it was initially a one-to-one relationship: only one search was possible at a time in a text buffer. It is now a many-to-many relationship: several searches can execute at the same time in the same text buffer (it can be useful for non-highlighted, background searches). And the search settings can be shared between several buffers.

Next step for my GSoC: rework the GtkSourceView style schemes to use CSS.

Search and replace in gedit and GtkSourceView

My GSoC on GtkSourceView/gedit/… is coming along nicely. Here is a screenshot of the new search in gedit:

New gedit search
New gedit search

The visible new thing is the “298 of 703” in the search entry, that shows the position of the current search match, and the total number of occurrences. This is just the tip of the iceberg, as much of the work has been done under the hood. Ignacio (nacho), my mentor, has improved GdTaggedEntry, and I worked on the new API in GtkSourceView, and adapted gedit to use the new API.

Note: almost all my work has already been merged upstream, but not the new search entry.

Search and replace API in GtkSourceView

The new API in GtkSourceView is available. One thing is missing though: regex search.

Why you should use this API:

  • It is asynchronous, i.e. the user interface is normally not blocked when the GtkTextBuffer is scanned. And the asynchronous overhead is small;
  • The search matches are highlighted;
  • You can get the total number of occurrences and the position of a certain occurrence easily;
  • For each search, the buffer is scanned at most once. Once the search occurrences are found, navigating through them doesn’t require to re-scan the buffer, thanks to gtk_text_iter_forward_to_tag_toggle(). As a result, most operations are really fast;
  • The regex search (still to come) will normally do multi-segment matching, also called incremental matching: when a partial match is returned, we take a bigger segment. No need to waste memory space to retrieve the entire buffer contents.

Nice, isn’t it?