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.

Switch SSD mode from RAID to AHCI (for Windows and Linux dual boot)

On some computers, such as the new Dell Pro Max Tower T2 and the older XPS 13, the SATA operation mode for the SSD is set to RAID by default.
Linux will not recognize the SSD in RAID mode; you need to change it to AHCI.
If you just change it to AHCI in BIOS, Windows will not boot.

The idea is to boot Windows in Safe Mode once, then change the SATA mode to AHCI in BIOS, then boot Windows normally (it will automatically load the AHCI drivers).

WARNING: Do the procedure at your own risk!

The procedure can be found in many places online.
However, I decided to put the steps that worked for me here:

  1. Click the Start Button and type cmd; Right-click the result and select Run as administrator
  2. Type this command and press ENTER: bcdedit /set {current} safeboot minimal (If it does not work, use this alternative: bcdedit /set safeboot minimal)
  3. Restart the computer and enter BIOS Setup (in Dell, it is F2)
  4. Change the SATA Operation mode to AHCI from RAID
  5. Save changes and exit Setup, and Windows will automatically boot to Safe Mode.
  6. Do as in the first step to open an elevated command prompt.
  7. Type this command and press ENTER: bcdedit /deletevalue {current} safeboot (If it does not work, use this alternative: bcdedit /deletevalue safeboot)
  8. Reboot once more, and Windows will automatically start with AHCI drivers enabled.

Note that in the Dell Pro Max Tower T2 BIOS, you must enable the “Advanced Setup” (see the top-left corner) to be able to change the operation mode in the “Storage” section:

Here are the sources I used:

Managing KDE Dotfiles with Chezmoi and Chezmoi Modify Manager

If you’re a KDE user who wants to keep your desktop configuration under version control, you’ve probably discovered that KDE’s configuration files can be quite challenging to manage with traditional dotfile tools. KDE stores settings in complex INI files that frequently change, contain system-specific data, and include sections you may not want to track. This is where Chezmoi Modify Manager becomes useful when using the Chezmoi dotfile manager.

The Problem with KDE Configuration Files

KDE applications like Kate, Dolphin, and KWin store their settings in INI-style configuration files. These files often contain:

  • Volatile sections that change frequently (like window positions, recent files)
  • System-specific data (like file dialog sizes, screen configurations)
  • Mixed content where you only want to track specific settings

Things have improved recently in that respect; however, some KDE INI files still mix those configurations.

Managing these files directly with Chezmoi would result in noisy diffs and configurations that don’t work well across different machines.

Enter Chezmoi Modify Manager

Chezmoi Modify Manager acts as a configurable filter between your actual config files and your Chezmoi repository. It allows you to:

  • Ignore entire sections or specific keys
  • Set specific values while ignoring everything else
  • Use regex patterns for flexible matching
  • Transform values during processing

The tool works by creating “modify scripts” that tell Chezmoi how to process each configuration file.

Quoting from the official documentation:

For each settings file you want to manage with chezmoi_modify_manager there will be two files in your chezmoi source directory:

  • modify_<config file> or modify_<config file>.tmpl, e.g. modify_private_kdeglobals.tmpl
    This is the modify script/configuration file that calls chezmoi_modify_manager. It contains the directives describing what to ignore.
  • <config file>.src.ini, e.g. private_kdeglobals.src.ini
    This is the source state of the INI file.

The modify_ script is responsible for generating the new state of the file given the current state in your home directory. The modify_ script is set up to use chezmoi_modify_manager as an interpreter to do so. chezmoi_modify_manager will read the modify script to read configuration and the .src.ini file and by default will apply that file exactly (ignoring blank lines and comments).

Note that this is based on the Chezmoi mechanism of “modifying scripts”, allowing you to manage only some parts of files.

Thus, the integration with Chezmoi is based on these mechanisms:

  1. Source files (.src.ini) contain your desired configuration
  2. Modify scripts (starting with modify_) define filtering rules
  3. Chezmoi applies the modifications when deploying configs
  4. The .chezmoiignore file ensures source files aren’t directly copied

The file name after “modify_” and the file name of the “.src.ini” must follow the naming conventions of Chezmoi.

Your .chezmoiignore must include:

This prevents the source files from being deployed directly, letting Chezmoi Modify Manager handle the processing.

So, let’s see how to use that.

Real-World Examples

You can use the “chezmoi_modify_manager” command line to create the proper files.

Let’s look at how this works in practice with actual KDE configurations, based on my dotfiles (so I have already created these files):

KWin Configuration (kwinrc)

The file “modify_private_kwinrc”:

This script ensures only the relevant window manager settings are tracked (the file “private_kwinrc.src.ini”):

Global Shortcuts (kglobalshortcutsrc)

The names of the files are using the same convention already shown before.

For keyboard shortcuts, you might want to ignore certain dynamic sections:

This keeps your custom shortcuts while filtering out activity-specific bindings that may not be relevant across systems. The file “private_kglobalshortcutsrc.src.ini” is not shown because it’s quite huge.

Font Configuration (kdeglobals)

Sometimes you only want to track a single setting:

This results in a clean config that only tracks the terminal font:

Kate Editor Configuration

For Kate, you might want to ignore volatile sections while keeping your editor preferences:

Again, the “.src.ini” file is not shown.

Benefits

  • Clean diffs: Only track settings you care about
  • Portable configs: No system-specific clutter
  • Selective tracking: Include only relevant sections

Drawbacks

In general, setting the files initially takes much more time: you need to understand what to include/exclude in the “modify_” scripts and properly craft the “.src.ini” files accordingly. Moreover, some Chezmoi mechanisms, such as “merge,” will not function. Therefore, updating the files requires employing alternative techniques, as outlined in the next blog post. Finally, besides “chezmoi”, you need to install an additional program “chezmoi_modify_manager”.

Eclipse in Wayland (2025)

Let’s see what Eclipse looks like in Wayland in 2025.

I report some screenshots of a few Wayland Window Managers and Desktop Environments.

Sway

Eclipse looks good in Sway:

Hyprland

The same can be said for Hyprland, especially now that the infamous bug has been solved:

GNOME

No problems on GNOME either; I’d expect that since it is “natively” based on GTK:

If I run Eclipse forcing X11 (GDK_BACKEND=x11), I see no difference.

KDE

On KDE, the situation is not bad, but I find it far from optimal.

Eclipse on Wayland doesn’t look completely native on KDE Plasma:

Many parts don’t look sized correctly.

There’s also the strange thing of the window title bar for the splash screen, which, of course, is not expected:

Dialogs also look not properly sized:

In X11, it looks better, or at least better integrated with the KDE desktop. Moreover, there’s no additional titlebar in the splash screen, and the dialog looks better (for size and width):

That’s all for this post!

Using Unison File Synchronizer on macOS: Now Available via Homebrew

Unison, a powerful file synchronizer, has long been one of my favorite tools. However, installing Unison on macOS used to be a manual and sometimes cumbersome process, as detailed in my earlier guide.

The great news is that Unison is now available as a Homebrew cask! This means you can install it with a single command, leveraging the convenience and reliability of Homebrew’s package management.

To install Unison, simply run:

This command will download and install the Unison application into your /Applications folder.

After installation, you might encounter permission issues due to macOS’s security features (especially if you downloaded the app from the internet). To clear any extended attributes that might prevent Unison from launching, run:

This command removes quarantine flags and ensures Unison can start without macOS warnings.

For more details and troubleshooting tips, check out my earlier guide.

Installing EndeavourOS Linux 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.

I previously blogged on installing Ubuntu on my old MacBook Air. Everything mainly went smoothly, except for the WiFi, which was not working during and after the installation, but it could be fixed by installing the proper module. The upgrade to Ubuntu 25.04 was almost fine: after the upgrade, the system did not boot anymore; I didn’t even get the Grub menu.

Ubuntu once again disappointed me. Time to wipe everything and go with my favorite Arch Linux distribution: EndeavourOS. In particular, “Mercury Neo”.

Installation

After having put the EndeavourOS 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 the Ventoy menu.

After some time, here’s the live system:

Did you notice the WiFi icon? Exactly! The WiFi has been automatically detected! Well done!

This is the WiFi card:

And we can see that the corresponding kernel module is part of the live system (of course, it will also be part of the installed system):

I changed the keyboard layout for an easier installation.

Before starting the installation, I use the Welcome menu to update Arch and EndeavourOS mirrors, of course, after connecting to the WiFi.

Before going on, everything seemed to work: touchpad, keyboard light, volume, brightness, though function keys were inverted. We’ll fix that later.

Let’s start the installation, choosing the “Online” method:

Then, the installation, based on Calamares, is the standard one, showing a few dialogs to select some configurations:

I will install KDE:

I also select as additional packages the LTS kernel and the printing packages:

As usual, I choose Grub as the bootloader:

I choose to wipe everything, select BTRFS as the file system, and also “Swap with hibernation”:

Let’s review everything and choose “Install”:

The installation takes a few minutes. Time to restart:

The installed system

Here we are:

Here are some screenshots of the good-looking KDE desktop:

And, of course, the fastfetch output in all its glory:

Configuration

As already stressed, unlike Ubuntu, there’s no need to fix any WiFi problem: it works out of the box!

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). You can try:

If it works, change this permanently:

Concerning hibernation (selected during the installation), it does work; however, there’s a big problem: the system does not shut down, it reboots. Upon rebooting, it effectively resumes from hibernation, but as it is, it’s rather useless. I still have not figured out how to fix that.

Another thing not working is the webcam.

This is the device:

Maybe it’s just a matter of installing the corresponding packages, but I haven’t investigated further yet.

Everything else works smoothly, as I have already said (including touchpad gestures in KDE).

Final thoughts

The laptop works great with EndeavourOS, even better than 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-saving setting:

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 KDE 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, even more so with EndeavourOS instead of Ubuntu! 🙂

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.