Author Archives: Lorenzo Bettini

About Lorenzo Bettini

Lorenzo Bettini is an Associate Professor in Computer Science at the Dipartimento di Statistica, Informatica, Applicazioni "Giuseppe Parenti", Università di Firenze, Italy. Previously, he was a researcher in Computer Science at Dipartimento di Informatica, Università di Torino, Italy. He has a Masters Degree summa cum laude in Computer Science (Università di Firenze) and a PhD in "Logics and Theoretical Computer Science" (Università di Siena). His research interests cover design, theory, and the implementation of statically typed programming languages and Domain Specific Languages. He is also the author of about 90 research papers published in international conferences and international journals.

Speed Up Your Linux System with Zram

Zram, https://www.kernel.org/doc/html/latest/admin-guide/blockdev/zram.html, is a Linux kernel module that creates a compressed block device in RAM. This device can be used as swap space or a general-purpose RAM disk. By compressing data in memory, zram allows your system to store more data in RAM, reducing the need to swap to slower disk storage and improving overall responsiveness.

In particular, zram

  • Increases effective RAM capacity by compressing data.
  • Reduces disk I/O and wear, especially useful on SSDs.
  • Improves performance on systems with limited memory.

If you’re looking to boost your Linux system’s performance, especially on machines with limited RAM, zram is a powerful tool worth exploring.

In this post, I’ll show how to set it up on both Arch Linux and Ubuntu.

Installing zram

On Arch Linux

Install the zram generator package:

On Ubuntu

Install the systemd zram generator:

Configuring zram

Create a configuration file to set up your zram device. For example, to allocate half of your system’s RAM to zram and use the efficient zstd compression algorithm, run:

After saving the configuration, reboot your system to activate zram.

By default, zram will have the precedence over an existing swap partition.

You can use the command zramctl to see the status of zram and swapon to show your swap partitions (zram’s one will be /dev/zram0).

Install Nerd Fonts on macOS with Homebrew

I like Nerd Fonts a lot, and blogged about those in the past. If you spend a lot of time in the terminal, you’ve probably heard of them: they patch popular programming fonts with a huge set of icons, making your terminal and development environment look great and more informative.

Here’s how you can easily install Nerd Fonts on macOS using Homebrew.

Step 1: Install Homebrew (if you haven’t already)

If you don’t have Homebrew installed, open your terminal and run:

Step 2: Install fontconfig

Before installing fonts, it’s a good idea to have fontconfig:

Step 3: Install Nerd Fonts with Homebrew Cask

Homebrew makes it easy to install fonts with the --cask option. Here’s how I install my favorite Nerd Fonts:

You can add or remove fonts from this list as you prefer. Homebrew will handle downloading and installing them for you.

Step 4: Use Your New Fonts

After installation, open your terminal or code editor’s settings and select your preferred Nerd Font from the font list. Now you can enjoy enhanced icons and a better coding experience!


Tip: You can browse all available Nerd Fonts with:

Happy fonts! 🙂

Better diffs in Lazygit with delta

If you use Lazygit as your terminal Git UI, you know how convenient it is for staging, committing, and managing branches.

I use it in Neovim (LazyVim already configures it).

Integrating a custom pager (Lazygit Custom Pagers Documentation) can dramatically improve how diffs are displayed.

In this blog post, I’ll document how to use delta: a syntax-highlighting pager for git, diff, and grep output.

Delta makes diffs much more readable by adding syntax highlighting, line numbers, and custom themes. This is especially helpful when reviewing changes in Lazygit, as it makes it easier to spot what’s changed at a glance.

Installing delta

On Arch Linux (or derivatives), you can install delta with:

For other platforms, check the delta installation instructions.

Configuring Lazygit to use delta

To use delta as the pager in Lazygit, add the following to your ~/.config/lazygit/config.yml:

This tells Lazygit to use delta for displaying diffs, with color always enabled and paging disabled (since Lazygit handles paging itself).

Here are two screenshots with the diffs better highlighted:

Show line numbers

If you want to see line numbers in your diffs, update the pager line with “–line-numbers”.

Customizing delta with themes

Delta supports custom themes for even better readability. You can find a collection of themes here.

To use these themes:

  1. Download the raw themes.gitconfig file, for example, to ~/.config/delta/themes.gitconfig:

  2. Include it in your global Git config by adding the following to your ~/.gitconfig:

  3. To see available themes, run:

  4. Pick a theme you like (e.g., colibri) and enable it in your Lazygit config:

For example, with the “colibri” theme:

With “weeping-willow” theme:

Enjoy your diffs! 🙂

Computing the total test execution time of Maven Surefire

When working with Maven projects, the Surefire plugin is commonly used to execute tests, but it lacks a built-in feature to display the total execution time across all test suites. This can be particularly important when monitoring performance trends in larger projects with many test classes.

Maven’s Surefire plugin reports execution time for individual test classes but doesn’t provide an aggregated view of the total test execution time. The reports are generated in the “target/surefire-reports” folder, both as text files and XML files.

Here’s a shell script that parses the XML report files generated by Surefire and calculates the total execution time. The script is compatible with both Linux and macOS environments.

These are the steps:

  1. Look for lines containing <testsuite> tags
  2. For each matching line, loops through all fields (words) in the line
  3. Find fields that start with time=
  4. Uses gsub() to extract just the numeric value by removing the time=" prefix and the " suffix
  5. Add the extracted value to the running total
  6. Format the output in the same way, with the total time in seconds

To make this script run automatically after your tests, you can integrate it into your Maven build process using the exec-maven-plugin:

The above snippet assumes the script is in a file “report-total-time.sh” in the same directory as the POM. Otherwise, you’ll have to adjust the argument accordingly.

When your tests complete, you’ll see output similar to:

That’s all!

Using Neovim in Gitpod

I’m going to show you how to use Neovim on Gitpod. This can be useful for checking and testing your Neovim configuration.

The example can be found here: https://github.com/LorenzoBettini/neovim-gitpod-example.

I’m using a LazyVim distribution as a demonstration.

The Gitpod custom Dockerfile, “.gitpod.Dockerfile”, must be tweaked to install Neovim and its requirements (especially for using Lazyvim):

Then, the file “.gitpod.yml” must be tweaked accordingly; in particular, I’m using “stow” to create a symlink for the default Neovim configuration directory using as the source the configuration directory of this repository (you could also simply use the “ln” command for that):

The “stow.sh” script is part of the repository. I also specify a few extensions to install in the VScode of Gitpod.

Note that the first time, it will take a few minutes for Gitpod to provision such a Docker image.

Once in Gitpod, we can see that the link has been already configured:

Now, let’s enlarge the Terminal view and start Neovim.

We should see Neovim is installing all the packages as configured by LazyVim:

Note the change of the default color scheme:

Let’s close the Lazy window and see the Dashboard:

Since I’m using a light theme for the VScode, upon restarting Neovim, the color scheme is changed to its light variant as well:

We can now open the explorer (“space e”) to browse the contents:

By default, we have the Lua LSP installed.

We can use the file picker (“space f”):

We can use Lua LSP features like code completion:

And hover (“K”):

And change the color scheme with the picker (“space u C”):

Note that there are a few things that are not working correctly in Gitpod concerning Neovim:

  • Clipboard does not work since there’s no “DISPLAY” set.
  • Missing nerd fonts, things like folders and file types in the explorer, are not rendered correctly.

That’s all!

Installing Ansible and Molecule in Arch Linux

Using “pip” is the supported installation method for Ansible and Molecule. Let’s install Python libraries and applications (in this case, Ansible and Molecule) in a Python virtual environment. (This post is similar to the one about Ubuntu.)

First, install the required packages, including the Python virtual environment package:

Create a virtual environment somewhere (in this example, I create it in my home folder as a subdirectory of a folder for all the virtual environments; the directory will be created automatically):

Once the virtual environment has been created, “enter” the virtual environment:

Install the Python packages for Ansible, Molecule, and its plugins in the virtual environment:

You can verify that everything is installed correctly, e.g., at the time of writing:

Each time you want to run Ansible or Molecule, just run the “source” command above:

And then you can run “ansible” and “molecule”.

When using “Oh My Zsh” with the “Powerlevel10k” theme, you also get the virtual environment name shown in the prompt:

Experiments with Copilot Agent: Implementing a Maven plugin

I experimented with Copilot “Agent mode”: I told it to create a Maven plugin. (Let me stress that I already have some experience implementing and testing Maven plugins.)

I’ll report my experience, which has been positive in some respects but disappointing in others.

I use “Claude 3.5 Sonnet” model because that’s the one used in most demos I saw online.

This is the initial prompt:

I want to create a Maven plugin, using the official archetype.

The groupId for the project must be “com.examples” and the artifactId must be “exampleplugin”.

The project must be part of a Git repository, with the standard .gitignore file (excluding typical generated artifacts of a Maven project and also other typical files that must be excluded, including OS typical generated files).

The project must be up-to-date with respect to dependencies and plugins, and it must use Java 21.

I want also to use the Maven wrapper in this project, using the latest version of Maven (but not Maven 4).

I also want the GitHub Actions workflow to build and test the project (including integration tests) for Linux, Windows and macOS.

Is everything clear? Do you have any question?

Here’s the first output, which correctly uses the command for the archetype:

Let’s continue and see how it goes:

The “.gitignore” ignores too many things: I want to keep Eclipse metadata files and directories.

So, before going on, I specify

The dot files for project’s metadata of the Java LSP must not be ignored (e.g., .classpath, .project, etc.); .vscode must not be ignored either

And the updated version looks right:

Then, it goes on updating versions and Java version; it also runs the command for the Maven wrapper:

It creates the GitHub Actions workflow and initializes the Git repository:

That’s the summary:

However, I’m not happy with the results.

It only updated the Java and Maven versions, but not the dependencies or plugin versions. The Maven wrapper is installed with version 3.9.6, but the latest version of Maven is 3.9.9.

The GitHub Actions workflow is not perfect either:

It only considers the “main” branch, and there’s no need to run two builds. However, it correctly detected the profile “run-its” for integration tests!

I then wrote this:

The tasks were almost correct.
There are a few things that must be fixed:

– The latest version of Maven (both in the POM and in the wrapper) is not 3.9.6: it is 3.9.9.
– The GitHub Actions workflow only considers the “main” branch (both for push and pr); this is not what I asked: I want to build any branch. Moreover, there’s no need to run Maven twice (as long as integration tests are run).
– Moreover, I asked to update all dependencies and plugins to their latest versions, but that’s not what happened.

As a result, the GitHub Actions workflow was fixed according to my requests.

It also updates the Maven wrapper version and verifies the correct changes in the properties file.

It also updates a few versions in the POM, reporting:

However, most of the dependencies and plugins are NOT up-to-date at all.

I then wrote:

Please, double check the dependencies and plugins: you have updated them, but some of them are not yet at the latest version.

It seems to understand that it can use the Maven versions plugin to display the dependency updates:

After running the command, it complains it cannot read the updates from the output (which, instead, are there) and tries to use another command (which is completely wrong):

I told it about the visible versions:

The versions were actually visible in the output.

And here’s the result:

Unfortunately, when it uses such information to update the POM, it makes a small disaster: most dependencies are not correctly updated, and some versions don’t exist.

I told it about that, in particular, instead of displaying updates, it could have used the proper goal of the Maven versions plugin:

Some versions are still not up-to-date, not to mention that there’s also a wrong version that cannot be resolved. Why don’t you simply use the Maven versions plugin to update dependencies and plugins instead of just displaying their output and parsing it?

But it insists on displaying and trying to change the versions (without succeeding).

So I tried to be clearer:

That only displays the latest versions and then you’ll have to parse the output, which did not work yet. Isn’t there a specific goal to also update automatically all the dependencies and plugins?

Now it understands and uses the proper goal:

It then detects that some previously updated versions were wrong, and that there are beta versions of some dependencies and plugins; the run Maven command has already updated the POM, but it insists on rechecking the versions:

Updating some versions prevents the test from being compiled anymore. Copilot did not realize that. I make it explicit:

The test file contains a compilation error. I guess you updated the corresponding dependency to a too much high version (beta version). It’s better not to use beta versions and instead use the latest version before the beta one.

Now, it starts iterating, trying to downgrade some versions. It performs several iterations and asks whether it should continue. I say yes, and at some point, it seems to make the test compile again, but looking at the versions in the POM, it looks like it almost randomly decreased versions too much. Note that, by looking at the Maven central repository, it is easy to take the latest dependency version or a plugin that does not contain “beta”.

Anyway, after the test is finally compiled again, it decides to run the Maven build to see whether everything works. That’s the first time Copilot proposes to run the Maven build (I would have expected that to be done after creating the files with the first prompt).

Here comes trouble:

The test fails (Google Guice fails when using dependency injection). It looks like Copilot understands there’s a misalignment with dependencies. In particular, trying to fix the previous compilation error, it wrongly added additional transitive dependencies (uselessly) with wrong versions, leading to this failure.

It then starts several iterations without being able to fix the test.

Ultimately, I had to revert the changes to the POM: all the previous iterations about version updates were useless and disruptive.

In the end, I was impressed by the first iterations where Copilot took most tasks correctly.

However, it clearly cannot handle tasks like version updates or compilation failures (at least, without breaking tests afterwards).

I managed to guide it in some parts because, as I said at the beginning, I know how to implement and test Maven plugins. Without such an existing experience, I had to give up very soon.

After all, this was just an experiment. Bootstrapping the project and the Git repository manually with the archetype, updating a few initial versions, and creating the GitHub Actions workflow would have taken me only a few minutes: much less than the time I spent with Copilot 😉

Maybe the “Claude 3.5 Sonnet” model was not the right one? As I said, I saw this is used in most online demos for Copilot agent mode.

I’ll do some further experiments, so stay tuned!

Using Flash remote in Neovim

The “remote” feature of flash.nvim is handy: it acts in “operator pending mode” to perform operations and then return to the original position. It took me some time to understand what it was doing, so I’m writing about it.

I’m using it in the LazyVim distribution, which enables “flash” by default (and also “which-key”, which is the window showing possible commands to complete the sequence).

Let’s take this buffer (note the current position of the cursor):

Let’s assume I want to copy (“yank”) the line containing “the very first…”. I press “y”, which goes into “operator pending mode”:

Then “r” for “remote flash”, and start typing something in that line, e.g., “location”; I type “l”,

Labels appear in the occurrences (remember that with “flash”, you should look at the word you want to jump to while you’re typing); in this example, a single letter allows you to have useful labels for jumping to the desired occurrence. You might need to type a few more letters in more complex files. I press the label corresponding to the occurrence of “location” in the interested line (“h”)

The cursor temporarily goes to the desired occurrence of “location”; then, I press “a” for around:

Finally, “p” for “paragraph”. Now the desired line has been yanked, and the cursor automatically goes back to the original position:

I could then paste the line there, for example.

Let’s see another example with “d” for deleting a remote line.

Let’s see the starting point, in particular, the current cursor position on line 18:

Let’s say I want to delete the word “very” a few lines above.

I enter “operator pending mode” with “d”

Then “r” for “remote flash”, and start typing “very”; I type “v”,

Labels appear in the occurrences (remember that with “flash”, you should look at the word you want to jump to while you’re typing), and press the label corresponding to the occurrence of “very” in the interested line (“d” in this case)

The cursor temporarily goes to the desired occurrence of “very”; then, I press “a” for around:

Finally, “w” for word. The “very” word is removed, and the cursor automatically goes back to the original position:

Try to do the same with “c” for change, to change something in a “remote” location and automatically return to where you were.

Pretty useful! 🙂

Installing Ansible and Molecule in Ubuntu Linux

Using “pip” is the supported installation method for Ansible and Molecule. In Ubuntu, just using “pip” will lead to the error “externally-managed-environment” because of the Python environment that is “externally managed” by the package manager (this prevents direct use of pip for system-wide installations to avoid conflicts or issues).

(This post is similar to the one about Arch Linux.)

Instead, let’s install Python libraries and applications (in this case, Ansible and Molecule) in a Python virtual environment.

First, install the required packages, including the Python virtual environment package:

Create a virtual environment somewhere (in this example, I create it in my home folder as a subdirectory of a folder for all the virtual environments; the directory will be created automatically):

Once the virtual environment has been created, “enter” the virtual environment:

Install the Python packages for Ansible, Molecule, and its plugins in the virtual environment:

You can verify that everything is installed correctly, e.g., at the time of writing:

Each time you want to run Ansible or Molecule, just run the “source” command above:

And then you can run “ansible” and “molecule”.

Neovim and LaTeX with LazyVim, part 1: initial configuration

This is the first part of a few tutorials on using the LaTeX typesetting system with Neovim using the LazyVim setup. I highly recommend LazyVim because it has many cool plugins configured with nice defaults. Moreover, as we see in this tutorial, it lets you quickly have VimTeX and the TexLab LSP up and running in Neovim.

You can follow this step-by-step tutorial by implementing the steps starting from a fresh LazyVim installation (see http://www.lazyvim.org/installation). If you already use LazyVim, you might want to do the steps in this tutorial on a fresh, separate Neovim configuration directory before applying all the configurations in your daily-driver Neovim configuration.

For example, if you start with the starter project provided by LazyVim, you can clone it into a separate configuration directory:

And then you start Neovim pointing to that configuration:

This way, your existing Neovim configuration won’t be touched, and you’ll be free to experiment with this new configuration.

In these tutorials, the path is always intended relative to the Neovim configuration path when referring to a configuration file. If you follow the above commands, for example, it will be relative to “~/.config/lazyvim-tex”.

I suggest you follow the tutorials by manually executing the configuration steps in a new, separate Neovim configuration.

The final result of this series of tutorials can be found here: https://github.com/LorenzoBettini/lazyvim-tex. Branches will denote the state of the repository according to a specific blog post part.

A few initial notes

The plugin VimTeX needs a LaTeX installation and a compiler; the default is “latexmk”.

In Arch Linux, you can install it like this:

You must also ensure a working LaTeX installation with all the needed packages.

I’ll use Zathura and Sioyek as PDF viewers, automatically providing bi-directional linking (synchronization) between the LaTeX sources and the PDF.

In Arch Linux, you can install Zathura like this:

For Sioyek, AUR packages are available.

I’ll use a light theme (“catpuccin-latte”) for Neovim instead of the default dark one in the screenshots.

The “localleader” will be remapped to “\”: VimTeX commands start with “l” and in LazyVim “<leader> l” (that is, “<space> l” is already mapped to “Lazy” commands). This remap is done automatically by the LazyVim “Tex Extra” I’ll use.

Let’s start

As a first LaTeX example, I’ll use this one from VimTeX: https://github.com/lervag/vimtex/blob/master/test/example-quick-start/main.tex. Download that file and put it somewhere in a subdirectory, e.g., “latex”. That LaTeX article also describes the main features of VimTeX and its commands and bindings.

Let’s open this file with the fresh Neovim distribution.

Let’s install the LazyVim “Tex Extra”. A LazyVim extra is meant to configure several plugins and configurations with a single mechanism. In this case, it will configure VimTex, the TexLab LSP, and other related plugins and keybindings.

You have some alternatives to enable an “Extra”, which is documented for each available “Extra”; for Java, see http://www.lazyvim.org/extras/lang/tex. I prefer to use the UI: Type “:LazyExtras” to show the LazyVim Extras UI:

The LazyExtras UI proposes some recommended extras based on the files you’ve just opened, so it should recommend “lang.tex”; if not, search for “lang.tex” and when you’re on that line, press “x” to install the extra.

You get the feedback about restarting Neovim so that VimTeX is installed.

Specifying an extra as we’ve just done creates a file in the configuration, “lazyvim.json”, with this content (the numbers for news and version might be different depending on when you follow this tutorial):

The idea is to keep this file in the Git repository for your configuration as part of your dotfiles for Neovim.

Once you reopen the LaTeX file, you should get feedback about Mason downloading the “texlab” LSP; this is done only the first time.

Of course, you could force the installation of “texlab” beforehand by using the Mason UI, “:Mason”: select “texlab” and install it.

Alternatively, if you want a fully automated solution that, besides installing all the Neovim plugins, also automatically installs the TeXLab LSP, you can add this Lua specification in the Neovim configuration folder (the name does not matter; I call it “extend-lsp” to stress that it extends the Mason configuration of LazyVim, https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/lsp/init.lua) “lua/plugins/extend-lsp.lua” with this content:

Now, when you start Neovim, “texlab” will automatically install. You might want to check whether Mason has successfully downloaded and installed it or is still installing it through the Mason UI.

You can now try to edit the file using the content assist, providing completions and possible templates:

Let’s explore VimTex commands; remember that we’ll use “\” as the “localleader”. Which-key will show the available keybindings:

Let’s compile the LaTeX file with “\ l l”. This will start the compilation, which, depending on the size and complexity of the LaTeX document, takes a few seconds.

In the end, if there are no compilation errors, it automatically opens the default PDF viewer (I’m on KDE, and the default PDF viewer is Okular):

With “\ l l” we instructed VimTeX to watch for file changes (you can stop it with “\ l k”). VimTeX will automatically retrigger compilation and update the PDF document in the viewer as soon as we change the file and save it. For example, let’s add a sentence, save, and when we get feedback about the completed compilation, we should see the result in the PDF viewer:

Let’s add a LaTeX error, save, and get the list of reported errors (selecting any error will lead to the corresponding line in the source file):

Configure the PDF viewer

Let’s configure Zathura as the viewer.

Let’s add this line in the file “lua/config/options.lua”:

I’m using “zathura_simple” instead of “Zathura” because, as documented, the latter requires “xdotool”, which I don’t have. This way, we avoid the warning “Viewer cannot find Zathura window ID!”.

Let’s restart Neovim, reopen the LaTeX file, and select “\ l l”.

Now, it will open Zathura with the highlighted part corresponding to the cursor’s current position in the source file!

Let’s move the cursor in the source file to another line and press “\ l v”: the selection in the PDF is updated accordingly:

The other way round also works: from Zathura, use “Ctrl + click”, and the cursor in the source file will be updated to the corresponding line (in the screenshot below, I did “Ctrl + click” on the part of “toggles between”):

This synchronization is super useful when writing in LaTeX, isn’t it? 🙂

Alternatively, I also use Sioyek as a PDF viewer, which works on macOS as well. In this case, the option for the viewer must be changed accordingly:

In Sioyek, to return to the source file, enter “synctex” mode with “F4” and right-click with the mouse.

Other features

Let’s open the “Table of Contents” window with “\ l t”:

Note the helpful help contents and the “TODO” elements that were also reported.

Stay tuned for more blog posts on LaTeX and Neovim! 🙂

Installing the Tmux Plugin Manager (tpm) with Chezmoi

Similar to what I had already shown in a previous post, in this post, I show how you can install (and keep up-to-date) the “tpm” (Tmux Plugin Manager) with Chezmoi, which I highly recommend!

Typically, you manually install “tpm” by cloning its GitHub repository into the proper directory:

Let’s do that automatically with Chezmoi instead.

Chezmoi offers mechanisms for such situations: https://www.chezmoi.io/user-guide/include-files-from-elsewhere/. In particular, I use “Include a subdirectory from a git repository”: this way, Chezmoi will clone the external Git repository on the first run and will keep it up to date (i.e., “git pull”) at some specified intervals (remember, the default interval is 0!).

You need to create the file “.chezmoiexternal.toml” in the root folder of your Chezmoi file and follow the syntax in the documentation.

Here’s what I need to install “tpm” by cloning its GitHub repository:

Note that I specified a 1-hour refresh interval. Thus, if I issue a “chezmoi update”, it will keep that interval into consideration when deciding whether to check for updates (i.e., “pull”) in the Git repository. However, you also have this option in Chezmoi to force the Git update:

That’s all, and enjoy your dotfiles! 🙂

Installing Ubuntu 24.10 on an old MacBook Air (2016)

I bought this laptop in late 2016. It’s still a good laptop (8 GB RAM, 128 GB SSD) and very light.

However, I cannot use it with macOS anymore.

Let’s put Ubuntu Linux on the laptop! I’ll write the installation instructions and the configurations for a fully functional Ubuntu on this MacBook Air, which runs fast and smoothly and brings the laptop back to life!

Although I am a big fan of Arch and EndeavourOS, I first decided to try Ubuntu on this MacBook. Maybe, in the future, I’ll also try using an Arch distribution.

Installation

After having put the Ubuntu 24.10 ISO on a USB stick with Ventoy and inserted the USB stick, Turn on the Mac and immediately press and hold the Option (⌥) key until you see the startup disk selection screen:

Select the entry corresponding to the USB and get to Ventoy menu:

After some time, you should see the familiar Ubuntu splash screen:

Unfortunately, when I got to the desktop, I discovered the WiFi card had not been detected.

I’ll fix that later, after the installation.

I can use my mobile phone: I enabled USB tethering after connecting the phone with a USB cable. USB tethering in Linux works like a charm. I can now go on with the installation with a working Internet connection!

The installation is the standard Ubuntu installation:

Since I don’t want to keep any macOS installation (the space on the SSD wouldn’t be enough anyway), I choose to wipe the entire disk and let Ubuntu select a standard partition scheme.

The installer correctly detected my time zone:

Let’s start the installation, which only takes a few minutes (even considering I’m using my mobile phone connection).

By clicking the terminal icon on the bottom right, you can see the logging of the installation:

Time to restart the installed system!

Configuration

Let’s start fixing the WiFi problem.

This is the WiFi card on the laptop:

It is enough to install these packages:

Reboot, and the WiFi is working great!

Then, let’s fix the function keys, which are inverted (so, to have F1, you’d have to press “Fn F1”, which is not ideal). This is documented here: https://help.ubuntu.com/community/AppleKeyboard#Change_Function_Key_behavior.

You can try:

If it works, you can change this permanently:

I have already blogged about Thunderbird and Firefox snap packages, which I don’t like, and how to get back to dep packages.

Final thoughts

As I had already anticipated, the laptop works great with Ubuntu. Everything is smooth and reactive. Even more than with the original old macOS operating system.

I noted that concerning sleep, the default configuration already uses the more power save setting:

Everything else works great, including all the volume and screen brightness function keys. Moreover, the screen light automatically adjusts depending on the environment illumination!

Power consumption also works fine after installing the powertop package (running that with the “auto-tune” setting) and setting the power profile to “Power Saver” from the Gnome menu:

MacOS probably used to have better power consumption, but this one is acceptable.

It was a nice decision to put Linux on this laptop! 🙂

Disabling tracker-extract in Gnome 47 and 48

I like the tracker service in Gnome, which indexes files so that you can easily search for them from the Activity view or the file manager. However, I don’t like tracker-extract, which also indexes the file contents: I use Recoll for such a service, and tracker-extract uses too much CPU (it indexes new or modified files as you create/change them).

In the past, up to Gnome 45, I could disable tracker-extract only with

However, in Gnome 46, that service has gone, and in the Gnome discourse forum, https://discourse.gnome.org/t/can-tracker-extract-be-disabled-in-gnome-46/20782, I got a hint on how to disable it by removing the tracker-extract rules from “/usr/share/tracker3-miners/extract-rules/“.

Things have changed again in Gnome 47 (fortunately, they haven’t changed again in Gnome 48) because the directory is now named “/usr/share/localsearch3/extract-rules/“. Thus, the removal must be done like this:

If you want to keep a backup, you might want to move those files somewhere.

This is the script I’m using:

  • it works also in Gnome 46 (with the old directory name)
  • it takes a backup before removal

Use it at your own risk:

That works!

WARNING: as soon as tracker-extract is updated to a new version, those files will show up again, and you’ll have to remove them. Possibly, before logging into Gnome, to avoid that tracker-extract starts eating your CPU.

In the meantime, I also created this issue for Gnome: https://gitlab.gnome.org/GNOME/tracker-miners/-/issues/342.

GNOME 48 released on Arch Linux

Updated on 26 March 2025 with more screenshots about the new font.

GNOME 48 has just been released on Arch Linux! (And thus, also on EndeavourOS).

Unfortunately, many extensions have been turned off because they are not yet compatible (that’s quite usual with new versions of GNOME):

The most critical one is the first one above: the app indicator in the system tray. Let’s see whether it’ll be fixed soon.

My favorite new feature is the Adwaita fonts:

I like it a lot! Everything seems much more readable.

See, for example, Nautilus (I’m using a different icon theme, but the font is the default one):

Also, the monospace version of Adwaita looks nice:

To better see the difference, here’s a screenshot with the old fonts:

And here’s one with the new Adwaita fonts:

 

Besides other new features you might find in many articles, I also appreciate that the default image viewer now provides some basic editing features (note the toolbar icon):

At least, the editing operation I use most, “cropping”, is there. Changing the size is not yet possible. That’s why I also use Gwenview in GNOME.

Let’s hope they fix extensions soon 🙂

A first look at Copilot in Eclipse

Microsoft announced the public review of Copilot for Eclipse.

I immediately tried that in one of my Java projects.

Use the “Market Place” to install Copilot in Eclipse:

Once you click install, you must “trust” the contents to be installed:

Once installed and restarted Eclipse, you must authenticate with your GitHub Copilot account by clicking on the Copilot icon in the bottom right:

This will open a dialog with a code you must insert in the opened web page. Note the button to automatically copy the code in the clipboard and open the browser:

In the browser, you’ll have to authenticate in your GitHub account and paste that code (which should be in the clipboard). If everything goes fine, the webpage will tell you that everything is in place to start using Copilot in Eclipse, and Eclipse should show the corresponding success dialog:

I started to do some experiments.

I have this test code where Eclipse shows a warning on the “FileOutputStream” because the resource is not closed. Of course, I know how to solve that: use a try-with-resource block. But let’s ask Copilot.

I opened the file and the Copilot chat (still using the button in the bottom right toolbar):

Here’s what I asked:

I experienced a possible UX design problem here: I didn’t see any answer. I had to enlarge the view to see where Copilot wrote the answer (note in the same part where I wrote the question):

The answer is wrong: that is not the cause of the warning, and that is not the solution.

I tried to be more explicit in the question, detailing the message of the warning:

OK, this time, the answer is correct!

I tried to use the toolbar button to insert the solution in the editor:

However, instead of replacing the interested part, it just inserted that code starting from the editor’s cursor: a disaster of course 😉

Instead of manually copying and pasting the solution, I experimented with Copilot code completion. As I said, I know that I must use a try-with-resource. I converted the lambda expression into a block and typed “try (“. The grey code is suggested by Copilot:

I don’t know whether this is due to the selected solution in the chat or to my previous question, but the proposed code is correct! Press TAB to accept that. Then, I manually removed the duplicate original line. Maybe the original line has been used to propose the correct completion.

For the other part in the same file with the same warning, the completion was done in two steps: I started typing as before, accepted the initial partial condition, went on typing some more, and got the rest of the correct completion:

I also tried asking how to move the Maven project to Java 21 by opening the POM and using the chat:

The answer is correct, but honestly, the question was relatively trivial 😉

Unfortunately, Copilot code completion in the POM file does not work well: it tends to interfere with the default content assist in the POM; I haven’t found a way to use that properly.

Other valid key bindings:

  • Ctrl + Alt + / to manually trigger Copilot’s code completion;
  • Ctrl + Right to accept the next word in a suggestion.

Let’s see for future updates 🙂

In the meantime, I’ll try to experiment with that further.

Amarok is finally available on Flathub

I have always liked Amarok, the (initially) default KDE media player. It’s very feature-rich, nothing compared to Elisa. Moreover, it has two crucial features that I haven’t found in any other players:

  • it saves statistics (play count and stars) directly into the music file
  • it synchronizes statistics with the iPod.

I have always liked Amarok, the (initially) default KDE media player, and I have already blogged on installing it in Arch Linux and Fedora through its flatpak repository.

Now, installing Amarok on any Linux distribution is easy: it’s available from Flathub!

Once flatpak is configured correctly on your distribution, you just need to run:

Quoting from previous posts on Amarok, it’s also best to install Flatseal for configuring the flatpak application permission:

Let’s start Flatseal and check the Amarok permissions. Some settings are already configured to allow Amarok access to a few standard directories and databases. In my case, I also configure the access to all my files and a mount point because I have my music stored on an external drive, which I mount at that mount point “/media/bettini/backuplinux”):

You can now start Amarok either from the Gnome menu or from the command like:

IMPORTANT: The flatpak version of Amarok stores its files in

instead of the standard directories “.config” and “.local”.

If you want to connect your IPOD, first you must ensure that the “libgpod” package is installed, and then you have to add the permission access in Flatseal to the mount point of your IPOD. Otherwise, Amarok will detect your iPod but as a non-initialized one because it cannot access its contents:

If the Flatseal permissions are set correctly, you can enjoy your Amarok iPod!

Enjoy your music! 🙂

A first look at Pop!_OS Cosmic DE

I’ll briefly review the (currently in alpha 6) Cosmic DE in Pop Os 24.04 from System76 implemented in Rust.

The installation is smooth and easy to follow, based on standard dialogs:

I’m selecting “Clean Install” here because I’m testing it on a virtual machine.

There’s also the chance to encrypt the drive, but I’m not trying that.

The installation process is fast, and it only takes a few minutes.

It’s time to restart the installed system.

It’s a nice-looking DE, clearly inspired by GNOME, with a nice dock.

There are also a few beautiful wallpapers, all related to the space.

Generally, the DE is very responsive and smooth, though there are still graphical glitches now and then. Remember, it’s still in the alpha stage.

The DE comes with a few typical applications, like a terminal, a file manager, and a text editor; from what I understand, they’ve all been written from scratch. Although these applications look neat and clean, they don’t seem feature-complete yet, at least comparing them to Gnome or, even better, KDE-corresponding applications.

The file manager automatically changes the size of the icons when resizing its window.

However, there’s no way to have a tree view.

The terminal allows for some theme customizations, like custom profiles and also the beautiful transparency effect (by the way, note the style of application settings in Cosmic applications):

The above screenshot also shows the installer’s default partition layout.

However, currently, the terminal only allows you to either “Select All” or the text visible on the screen: while selecting, scrolling does not work.

Then, we have the application launcher that also looks clean and neat:

The launcher that appears with SUPER is very helpful. Note that by default, it shows the windows that are currently opened so you can quickly select one of them, e.g., by starting typing or by using the arrow keys:

Press “?” for more options:

The “File Search” looks interesting: I seem to understand that it relies on the standard “find” (or maybe “fd”) to show directories and files inside of them (see the found text file), though I haven’t tried that with actual directories full of tons of files.

The Google search also looks interesting:

The software center, with the “updates” functionality, looks fine:

Let’s now come to the well-known Pop OS “tiling” features:

The tiling features are nice. Also, the shortcuts make navigating and moving tiled windows very easy. During the moving, you also get nice effects.

In the “Settings” application, you can tweak many settings.

The “Appearance” setting, besides the standard “light” or “dark” mode, also allows you to change the accent color (I switched to green).

You also have additional appearance and theming settings, including icons.

By the way, I love the thick and colored border indicating the focused window. Of course, you can remove it if you don’t like it. I find it nice-looking and useful for easily spotting which window you’re working on.

Speaking of settings, Cosmic adopts a textual file approach, which I greatly like. Configuration files of applications or parts of the desktop can all be found in subdirectories of “~/.config/cosmic”.

For example, this is the file with the terminal opacity:

And this is the accent color of the dark theme:

This makes it very easy to manage your dotfiles in Cosmic. It is much easier than Gnome, with settings stored in the “dconf” database, and KDE, with its configuration files spread around in “~/.config” with names you always have to guess.

Of course, you can customize the shortcuts:

Finally, you have fractional scaling if you want:

To conclude this first look at Cosmic, considering it’s still in the alpha stage, I was very impressed by its responsiveness, cleanness, and beauty.

However, if I had to use it as a daily driver, I’d probably use other applications for tasks like file explorer, terminal, and text editor.

I’ll have another look at this DE soon!

Neovim and Java with LazyVim, part 4: Running programs

This is the fourth part of a few tutorials on Java development with Neovim using the LazyVim setup.

This post assumes you have already read and applied all the steps of the first, second, and third parts.

You need Java installed (possibly 21), while Maven is optional.

I will use this Maven example during the tutorial: https://github.com/LorenzoBettini/maven-bank-example, part of my TDD book.

The final result of this series of tutorials can be found here: https://github.com/LorenzoBettini/lazyvim-java. The “main” branch always points to the latest blog post.

The end of this part is still the branch “fourth-blog-post”.

Currently, we cannot run/debug anything, i.e., not even tests. We need the “nvim-dap” (debugger adapter), which is optional in the LazyVim Java extra (see the documentation, https://www.lazyvim.org/extras/lang/java). If the “nvim-dap” is installed, the LazyVim Java extra automatically configures the corresponding mechanisms for Java. Instead of installing the single plugin, we use another extra: https://www.lazyvim.org/extras/dap/core, which also installs other dap-related goodies, including the UI. We install the extra in one of the documented ways. As done before, I’m using the “:LazyExtras” UI, searching for “dap.core” and installing it. Of course, then we need to restart Neovim.

When you enable this extra, Mason must install additional packages: “java-test” and “java-debugger-adapter”. They are installed automatically (but you have to wait for their installation the first time you start Neovim; as usual, you can check the installation status using the Mason UI, “:Mason”).

Running

These plugins are configured so that the Java LSP can detect Java files with the “main” method. Let’s open such a file (in this example, “Main.java”). To start the application (in debug mode, though in this first run, we haven’t set any breakpoint), the command to search for is “Run/Continue” (not “Run with args”). In fact, “continue” is meant to continue a program under debugging that has stopped due to a breakpoint. Still, it is ALSO meant to start a program if there’s no program under debugging (that’s the documented behavior of DAP). Such commands can be accessed as submenus with “<leader> d” (“d” is for “debug”):

Let’s start this program with “c”.

In the dialog that appears, we select the “Launch” configuration (remember that you can type to fuzzy select):

This example contains a single Java file with a “main” method. If, in your program, you have several Java files with the “main” method, the LSP will detect them all and, upon launching, will show a picker to select the one you want to run.

The program doesn’t do anything interesting besides creating an object, calling a few methods, and logging something on the console. It terminates quickly, so you might see a few additional windows (the UI changes) for a second and then return to the source code. The UI that quickly appeared and disappeared is the “Dap UI”. As shown in the menus above, you can manually toggle it back with “<leader> d u” (as usual, I change the color scheme so that some parts of the UI are more evident):

For the moment, since we did not do any debugging, the only interesting window is the one at the bottom-right, showing the console with the output of the program we have just run.

Running with arguments

Let’s use “Run with Args,” which allows us to pass command line arguments to the Java application.

This application does not do anything with the passed arguments. Let’s change the “main” to print the arguments on the console. For example, adding this line at the beginning:

Select “<leader> d a”, and specify a few arguments:

We’ll see “[first, second, third]” in the console.

Custom launch configurations

Besides the automatically detected Java files with a “main” method, the LSP is configured to support VSCode launch configurations, which, by default, are searched for in the file at the root of the project “.vscode/launch.json”. The options for such files are similar to the ones found here: https://code.visualstudio.com/docs/java/java-debugging#_configuration-options, though the accepted JSON is not strictly the same, and some options might be different. The specific format accepted by Dap is documented in the Dap documentation (e.g., online at https://github.com/mfussenegger/nvim-dap/blob/master/doc/dap.txt or using the “:help dap-api”).

TIP: it might be a good moment to install the LazyVim JSON extra, as we have already seen before.

If you create in the root of the Java project the file “.vscode/launch.json”, i.e., “:e .vscode/launch.json”, the file is created with some initial contents:

For this example, I’m creating two additional launch configurations for passing some fixed arguments to the main file and another one that prompts the command line to pass:

Note that since these launch configurations do not specify the Java class with the main (see the corresponding option if you want to do that), they work correctly only when your buffer contains a Java file with “main”.

Let’s open the “Main.java” file and try to run the program with “<leader> d c”: we get this selection dialog to choose the configuration (where the first two are as before, and the other ones are taken from the “launch.json” above):

If you select the configuration with the prompt, you get another pop-up dialog where you can insert the command line arguments. The dialog is pre-filled with the default value specified above, “foobar”:

That’s all for this post.

In the next post, we’ll learn how to debug a Java program from Neovim.

EndeavourOS Mercury

I haven’t blogged about the EndeavourOS installation for a while.

Let’s have a look at the new EndeavourOS Mercury. I will install it with KDE Plasma into my LG Gram 16.

The installer has been featuring KDE Plasma instead of Xfce for a while:

Unfortunately, the screen isn’t automatically scaled, so it’s a bit too small. I could change the scaling, but I’ll leave it like that. As shown later, the first time I log into the installed KDE Plasma Wayland session, KDE will automatically scale the display to a comfortable size.

As usual, I must connect to the Internet and add my Italian keyboard layout. If you know KDE, it’s easy with its system settings:

Before starting the installer, I customize GRUB, as shown in my post.

Now that I’m connected let’s start the online installer:

And I also take the chance to update the mirrors (which the documentation says will now be part of the installed system):

You also have the partition manager if you want to partition in advance. I’ll use the partition program during the installation.

Let’s “Start the Installer”, and I choose “Online” as the method.

The default language proposed is Italian, which was detected correctly. However, I have always preferred English OS installations, so I changed it.

The location is detected correctly, and I keep the proposed settings for numbers and dates:

I have to change the keyboard layout to Italian:

As I anticipated, I’ll install KDE Plasma:

You can review the packages to install; these are the defaults:

As I usually do, I also install LTS kernel in addition (you never know) and Printing packages:

As for the boot loader, the default is systemd-boot, but I prefer the good ol’ grub:

For partitioning, you have lots of choices:

In this computer, I already have a few Linux installations, so I want to do a manual partitioning:

The crucial thing is to specify the current UEFI partition so that the new entry will go into the existing one. I select it and press “Edit”. I only must specify the “/boot/efi” mount point:

Let’s create the primary partition using the “Free Space”: select it and press “Create”. I specify 100 GB, the BTRFS filesystem, the point point “/” and a label:

One of the helpful features of this installer is that you can also specify the position of the partition: in this case, I choose to have the partition at the end of the free space by dragging the partition to the end:

Here’s the result:

I have two SSDs with a few partitions I want to be mounted on this installation. Thus, I select the other SSD:

I “Edit” the involved partitions with my preferred mount points:

I’m done with partitioning, and in the following window, I specify my user’s details.

Finally, here’s the recap:

Let’s start the “Install”.

Remember that during the slide show, you can toggle the logging (the button on the left of the percentage):

By the way, did you see the first slide about contributing? I’ve just contributed because I love EndeavourOS 🙂 You might want to contribute as well if you like this distro!

In about a few minutes (this computer is powerful), the installation finished without problems. Time to restart!

Rebooting says that a job is still running for “User Manager”, but hitting “Ctrl+Alt+Del” a few times forced the reboot.

Let’s log into the installed system (remember, the default is Wayland):

As anticipated, KDE automatically set the scaling to 125%, which could be fine for this laptop:

I changed it to 150% to have a more readable screen.

The Plasma theme is the “Breeze Dark EndeavourOS”, which is dark with a purple accent:

Now, it’s time to run my Ansible Role for KDE, and then I use Chezmoi for my dotfiles.

Everything went smoothly, and I have a working KDE desktop configured as I want.

Since I use BTRFS, I also set the snapshots with BTRFS Assistant.

The BTRFS subvolume layout implemented by EndeavourOS is nice:

Concerning “/etc/fstab”, I had to add the option “nodiscard” because the “fstrim.timer” already performs trimming once a week.

Once again, EndeavourOS provided a pleasant installation experience and a well-configured OS.

Enjoy it! 🙂

My Ansible Role for Nerd Fonts

Installing Nerd Fonts is easy in Arch Linux: they are in the official repositories. That’s not true for Ubuntu and Fedora. Of course, installing them in these distributions is also not complicated. Still, it is a manual procedure: download the font archive, extract it in a specific directory, and regenerate the font cache.

That sounds like an automation task for Ansible!

I created an Ansible role to install my favorite Nerd Fonts in Ubuntu and Fedora: https://github.com/LorenzoBettini/my_nerd_fonts_role.

You can find the instructions for using such a role in your Ansible playbooks.

Here, I briefly describe the main parts.

The file “tasks/download-font.yml” defines the tasks for downloading and extracting the zip archive after creating the destination directory:

The “tasks/main.yml” uses the above tasks, iterating through all the specified fonts to install. It also ensures that some packages are installed:

The variable “fonts_to_install” contains the list of font names to install based on the ZIP archives to download from the Nerd Fonts release site.

The file “vars/main.yml” contains my list of fonts to install:

That’s all: I use this role in my playbooks, and it installs all the Nerd Fonts I like best.

Enjoy your Nerd Fonts! 🙂