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.
The end of this part is still the branch “third-blog-post”.
In the first part, we saw how to enable Java LSP in the LazyVim distribution. We also saw a few interesting features for programming in Java in Neovim with such a configuration. In the second part, we saw a few of the IDE mechanisms we get from the Java LSP in LazyVim.
Let’s continue where we left off (remember, I’ll use the above-mentioned Maven project) and see how to deal with Maven dependencies.
Adding support for the pom.xml
By default, opening the pom.xml file gives only syntax highlighting but no LSP support:
We can install the XML LSP, “lemminx”, using Mason, e.g., by modifying the “extend-lsp.lua” file we saw above:
Lua
1
2
3
4
5
6
7
8
9
return{
"williamboman/mason.nvim",
opts={
ensure_installed={
"jdtls",
"lemminx",
},
},
}
Restart Neovim and open the “pom.xml” file again. Wait some time for Mason to install the LSP, and the first thing you might notice is the status line showing the structure of the current XML element:
The XML LSP is schema-aware so that it can provide hovering support (“K”):
It also provides the symbol mechanisms shown above. It provides auto-closing of tags and rename refactoring. Moreover, it can validate what you write according to the schema (in this case, it checks that it is a valid Maven XML).
It also implements a “code action” for quick-fixing it:
Some other notes
If you add a dependency to the POM or change one of the existing dependencies version, you must run “:JdtUpdateConfig” so the Java LSP can download the new dependencies.
In general, when something is not working, “:JdtRestart” might fix things.
In case of misalignments of the workspace, e.g., if you wipe the local Maven cache (“~/.m2/repository”) when restarting an already opened project, you get errors due to unresolved dependencies:
In such a case, you can run “:JdtWipeDataAndRestart”, which wipes the Eclipse workspace (not your project) and restart the LSP, which will resolve the Maven dependencies from scratch.
That’s all for this part!
Note that for the moment, we cannot start/debug a Java program from Neovim. We’ll cover that in the next part.
We still have to cover:
how to run/debug Java programs (with the current configuration, this is not yet possible);
When using Ansible and Molecule with Fedora 41, a few things must be adjusted so that Molecule can access the Docker image for Fedora 41.
This is probably due to some changes in the Python package and the new Dnf 5 package; if you use a default Docker Fedora 41 image, you get errors of the shape during the Molecule run:
1
"msg": "Could not import the libdnf5 python module using /usr/bin/python3.13 (3.13.1 ... [GCC 14.2.1 20240912 (Red Hat 14.2.1-3)]). Please install python3-libdnf5 package or ensure you have specified the correct ansible_python_interpreter. (attempted ['/usr/libexec/platform-python', '/usr/bin/python3', '/usr/bin/python'])"
To solve the problem, you must ensure that the packages “python3” and “python3-libdnf5” are installed in the Docker container used by Molecule during testing.
You can achieve that either by providing a custom Dockerfile for Molecule:
YAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
---
dependency:
name: galaxy
driver:
name: docker
lint: |
set-e
yamllint.
ansible-lint
platforms:
- name: fedora-gnome-instance
image: custom-fedora-default-ansible
dockerfile: ./Dockerfile
command: ""
privileged: true
build_image: true
...
and this is an example of a Dockerfile:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
FROM fedora:41
LABEL maintainer="Lorenzo Bettini"
ENV container docker
ENV LC_ALL C
ENV DEBIAN_FRONTEND noninteractive
RUN dnf -y update && dnf clean all
RUN dnf makecache \
&& dnf -y install \
python3-pip \
unzip \
sudo \
which \
python3-dnf \
python3-libdnf5 \
&& dnf clean all
...
Alternatively, you can specify the pre-built Docker Fedora 41 in the Molecule file:
YAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
---
dependency:
name: galaxy
driver:
name: docker
lint: |
set-e
yamllint.
ansible-lint
platforms:
- name: instance-fedora
image: fedora:41
pre_build_image: true
provisioner:
name: ansible
playbooks:
prepare: prepare.yml
...
And provide a “prepare.yml” file to install the above-mentioned required packages:
If you use the Homebrew package manager in macOS and you have macOS 12 because your Mac is too old to update to a new version of macOS, you can say goodbye to Homebrew: if you try to update your brew packages, you get such a message:
1
2
3
4
5
6
7
8
9
10
11
Warning: You are using macOS 12.
We (and Apple) do not provide support for this old version.
It is expected behaviour that some formulae will fail to build in this old version.
It is expected behaviour that Homebrew will be buggy and slow.
Do not create any issues about this on Homebrew's GitHub repositories.
Do not create any issues even if you think this message is unrelated.
Any opened issues will be immediately closed without response.
Do not ask for help from Homebrew or its maintainers on social media.
You may ask for help in Homebrew's discussions but are unlikely to receive a response.
Try to figure out the problem yourself and submit a fix as a pull request.
We will review it but may or may not accept it.
If you continue with the update or install a new package, you’ll have to wait a while; packages will be compiled from the source!
For example, on my old MacBookAir 2016, I only had a few homebrew packages to upgrade:
1
2
3
4
5
6
7
8
9
10
==> Outdated Formulae
bat icu4c@76 libxau python@3.12
ca-certificates jpeg-turbo libxrender readline
cairo libgit2 luajit sqlite
freetype libpng lz4 stow
fzf libssh2 neovim tree-sitter
gettext libtiff openjdk unibilium
git libunistring openssl@3 wget
glib libuv pcre2 xz
harfbuzz libx11 pixman zoxide
After 3 hours (!) I gave up! Things like “zoxide” or “neovim” depend on “llvm”, which, after 30 minutes, wasn’t yet compiled completely! The other dependencies of “zoxide” still take a lot to compile; for example (look at “z3”):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
==> Upgrading zoxide
0.9.4 -> 0.9.6
==> Installing dependencies for zoxide: libssh2, libgit2, z3, swig, llvm and rust
🍺 /usr/local/Cellar/z3/4.13.4: 120 files, 33.9MB, built in 23 minutes 7 seconds
...
Unless you’re willing to wait for several hours (I am not), I guess it’s time to say goodbye to Homebrew. As for me, it also means saying goodbye to macOS on this old MacBookAir (but still a capable computer) and trying to install Linux 🙂
Up to now, I have shown how to get started with Sway with the initial configurations and some other configurations.
Now, I’ll show how to install another status bar in Sway: Waybar (which is more powerful than the default Sway bar). Again, I’m going to do that for Arch Linux. As in the previous posts, I will NOT focus on the look and feel configuration. (This post is similar to the post about Hyprland and Waybar, but it’s specific to Sway).
Before continuing, the Waybar module for keyboard status (Caps lock and Num lock) requires the user to be part of the “input” group. Ensure your user is part of that group by running “groups”. If not, then add it with
1
sudo usermod-aG input$USER
Then, you must log out and log in.
Let’s install the package waybar:
1
sudo pacman-Swaybar
Let’s open a terminal and start Waybar (of course, it will appear on top of the current Sway bar at the moment).
1
waybar&
The result is not that good-looking:
Waybar heavily relies on Nerd fonts for icons, and, currently, we don’t have any installed (unless you have already installed a few yourself).
The terminal will also be filled with warnings about a few missing things (related to Sway) and errors about failures to connect to MPD.
Let’s quit Waybar (close the terminal from where you launched it), and let’s fix the font problem by installing a few font packages:
Let’s start Waybar again, and this time it looks better:
Try to click on the modules and see what happens. For some, the information shown will change (e.g., the time will turn into the date).
If you have “pavucontrol” installed (which should be the case for an EndeavourOS installation), clicking on the volume section will open the “pavucontrol” dialog for adjusting audio settings:
The “Caps” and “Num” locks should react according to the status of the corresponding keyboard keys. The section “it” shows that my current keyboard layout is “Italian.” if you configure several layouts and switch among them, that part in the bar will update automatically. And, of course, the workspace indicator works like in the default Sway bar.
Let’s quit Waybar again and change the Sway configuration to start Waybar instead of the default Sway bar. This section:
1
2
3
4
5
6
7
8
9
10
11
12
13
bar {
position top
# When the status_command prints a new line to stdout, swaybar updates.
# The default just shows the current date and time.
status_command while date +'%Y-%m-%d %X'; do sleep 1; done
colors {
statusline #ffffff
background #323232
inactive_workspace #32323200 #32323200 #5c5c5c
}
}
must be changed as follows:
1
2
3
bar {
swaybar_command waybar
}
Now, start Sway and enjoy Waybar.
Note that Waybar, by default, shows the Sway “mode”. For example, by default, SUPER+R enters the resize mode, where you can resize the current tiled window with arrow keys. The mode is indicated in the Waybar near the workspaces:
To customize the Waybar, create the configuration files for the Waybar (by default, they are searched for in “~/.config/waybar”). We can do that by using the default ones:
1
2
mkdir-p~/.config/waybar
cp/etc/xdg/waybar/*~/.config/waybar/
The above command will copy “config.jsonc” (with the configuration of Waybar modules, i.e., the “boxes” shown in the bar; The configuration uses the JSON file format) and “style.css” (for the style).
At the time of writing, this is the initial part of the configuration file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
// "layer": "top", // Waybar at top layer
// "position": "bottom", // Waybar position (top|bottom|left|right)
"height":30,// Waybar height (to be removed for auto height)
// "width": 1280, // Waybar width
"spacing":4,// Gaps between modules (4px)
// Choose the order of the modules
"modules-left":[
"sway/workspaces",
"sway/mode",
"sway/scratchpad",
"custom/media"
],
"modules-center":[
"sway/window"
],
"modules-right":[
"mpd",
"idle_inhibitor",
"pulseaudio",
"network",
"power-profiles-daemon",
"cpu",
"memory",
"temperature",
"backlight",
"keyboard-state",
"sway/language",
"battery",
"battery#bat2",
"clock",
"tray"
],
...
The initial parts specify the position and other main configurations. You can edit as you see fit by removing a module, moving it to another position, or enabling new ones. You might want to have a look at the Waybar Wiki for an explanation of the modules.
NOTE: I’m testing this configuration in a virtual machine, so modules like “backlight” and “battery” are not shown because there’s nothing corresponding to them in the virtual machine.
Remember that for each module you mention here, you can have a configuration in the rest of the file, e.g.:
Let’s add a configuration for showing a Taskbar to show all the running applications from all workspaces. This can be useful for quickly looking at all the running applications and quickly switching\ to any of them, especially in many workspaces. I’ll add it to the left section and remove the “custom/media” block, which I don’t use:
1
2
3
4
5
6
"modules-left":[
"sway/workspaces",
"sway/mode",
"sway/scratchpad",
"wlr/taskbar"
],
The module must also be configured to get the functionality that clicking on an element activates that element, possibly switching to the containing workspace (in this example, middle-click will close the window):
1
2
3
4
5
6
7
8
"wlr/taskbar":{
"format":"{icon}",
"icon-size":16,
//"icon-theme": "Numix-Circle",
"tooltip-format":"{title}",
"on-click":"activate",
"on-click-middle":"close"
},
Save the file, and reload Sway to see the block in action (I opened four different applications in four different workspaces):
The right-most section in the bar is a Tray, showing icons of running applications like Dropbox, Skype, or the Network Applet. Let’s install the latter one:
1
sudo pacman-Snetwork-manager-applet
Let’s configure Sway to autostart the “nm-applet”:
1
exec nm-applet
Let’s restart Sway, and now the Tray section is populated by the Network Manager Applet, which you can click and interact with, e.g., for editing connections or connecting to a WiFi network:
Let’s create a custom module for the Power menu, taking inspiration from the EndeavourOS Sway GitHub repository (I’ll change things a bit and simplify them; in particular, I’m going to use “rofi”, i.e., the package “rofi-wayland”, as shown in my previous posts, instead of “wofi”).
First, add the “custom/power” after the “tray” module:
LazyVim has just released version 14, with some new, interesting, and breaking features.
The first breaking feature is that Telescope is no longer the default fuzzy finder picker; the default is fzf-lua. I haven’t been using Neovim for a long time, but I do like Telescope, and I’m not sure I like the new picker.
Here’s a screenshot using Telescope:
Here’s the one using fzf-lua:
Maybe it’s just a matter of configuring the size and dimensions of the window, but I prefer Telescope: I can read the items better, while in fzf-lua, the list width is too short.
This can be seen better when using a folder with a deep subfolder, for example, based on my previous Neovim, Java, and LazyVim post. For example, with Telescope:
While with fzf-lua I can hardly see the names of the files:
The same holds when searching for keymaps (“<leader> s k”). Here’s Telescope:
And here’s fzf-lua (I don’t even understand the strange sequence of characters reported as “details” for some keymaps):
The news page tells you that you have to enable the “editor.telescope” extra to bring back Telescope as the default picker:
However, I went for the alternative shown on the “Telescope” page: it’s just a matter of setting an option (vim.g.lazyvim_picker = “telescope”) to use Telescope as the default picker:
Another change, which is not as breaking as the previous one but concerns the UI, is that the “which-key” interface now defaults to “helix”, so the useful which-key contents are not shown at the bottom of the screen as they used to be:
the contents are shown on the right:
I like this change: the which-key pop-up does not risk covering your buffer, and it can display more content more readably. With the old interface, when the cursor was near the end of the buffer, the interface could not show all the commands, and you had to scroll it. Now, it’s rarer for this to happen. I’ll keep it with the new “helix” preset.
If you look at the corresponding page, it is straightforward to change the corresponding “preset”:
The other breaking change is “blink.cmp as a replacement for nvim-cmp“; even in this case, you can revert to the old behavior by enabling the corresponding Extra. This doesn’t seem to break anything for me for the moment, so I’ll keep that.
You might also want to try the new keymaps; in particular, I like these ones:
The end of this part is still the branch “first-blog-post” (this blog post does not touch the configuration files).
In the first part, we saw how to enable Java LSP in the LazyVim distribution. We also saw a few interesting features for programming in Java in Neovim with such a configuration. In this post, we’ll see a few of the IDE mechanisms we get from the Java LSP in LazyVim. Let’s continue from where we left off (remember, I’ll use the above-mentioned Maven project).
Code completion and snippets
Let’s instead create a new Java file inside a source folder of this Maven project (e.g., starting from “src/main/java”), either with “:e <path>” or with the “Neotree” file explorer that comes installed and configured with LazyVim: toggle the explorer with “<leader> e”. I’ll create an Example.java inside the “app” subfolder: get to that folder, press “a” (for add), write the name “Hello.java”, and press ENTER to confirm:
Pressing ENTER again will open the empty file in a new buffer.
We’ll use snippets configured by default instead of writing all the contents, e.g., the correct package and the class implementation. Let’s enter INSERT mode and press Ctrl+SPACE. Start typing “cl”, we should get to the snippet we need (see the preview on the right): the one with all the correct contents:
Press ENTER to accept the snippet, and we get a valid Java class, with the cursor positioned inside the class’ body:
Let’s keep on using snippets to create a “main” method:
And a “System.out.println” statement:
Till you can write the “Hello World” string as an argument!
You might want to explore other useful snippets, like creating a public method:
Once the snippet has been selected, you have placeholders to edit the return type, the name, etc. Start typing to insert the return type, press TAB to get to the name, change the name, and press TAB to get inside the parenthesis to insert the parameters possibly. The final TAB will get you inside the method body. Shift TAB goes in the other direction.
Code actions
Let’s look at a few other features provided by LazyVim Java Extra. Note that these LSP-related features are not strictly related to the Java LSP but to the general configurations for LSPs. The same keybindings and mechanisms are meant to work with other LSPs, though not all LSPs implement all such capabilities.
You have code actions, using “<leader> c a”, which depend on the context you’re in the source file:
This menu is also handy for having the IDE fix errors for you (handy when you apply TDD); in Eclipse, we’d call them “quick fixes”, but in this context, “quick fix” is meant for quickly seeing all the diagnostics. For example, I intentionally refer to a non-existing symbol, and I use “Code actions” to have the IDE create that field for me (remember to exit insert mode to get the diagnostics; by the way, such dialogs can be filtered starting typing something to access the desired item quickly):
As another example, let’s change the package name in the “Hello.java” file we created above:
As expected, this makes the file invalid, as reported in the editor (and also in the explorer). Let’s use the code actions:
We use the first one because we want the file to be moved to the correct source directory:
Let’s do the opposite, press “c” in the Explorer to cut it:
move to the “app” folder and “p” to paste it:
The file is invalid again; this time, we use the second code action to change the package name in the file to respect the current source directory (remember that you must be in the buffer for code actions, not in the Neotree; you can use Ctrl + L to move to the right window):
Navigating through symbols
You might explore other features like showing symbols; there are many ways of achieving that in LazyVim and its default plug-ins. You can use “<leader> s k” to search for keybindings and start typing “Symbol”. Here are some examples.
“<leader> s s” gives you symbols with Telescope:
“<leader> s S” gives you symbols with Telescope in the entire workspace; the workspace is an LSP concept, but for the Java LSP, it can be seen as the Eclipse workspace that is being used under the hood: you get access to all the Java source files and all the types in the dependencies of the project. Start typing (be patient if you have a workspace/project with tons of dependencies), and you should see the classes of your sources and dependencies. In this example, we can access all the types starting with “Assert” from the JDK and the dependencies (in this project, JUnit, AssertJ, Log4J).
Selecting one will open it in the editor. If it comes from a dependency, the LSP will download the sources of the corresponding Maven artifact and show them in a read-only buffer.
“<leader> c s” gives you the “Trouble” symbol window, which is similar to the Eclipse Outline (note that it is synchronized with the editor; I changed the color theme to make selections more visible):
“<leader> c S” (capital “S”) gives you the “Trouble” window with references and calls to the currently focused element (again, the window is kept synchronized):
Then you have all the navigation capabilities, typically starting with “g,” like goto definition or goto references (opening a telescope picker for all the references in the workspace). You can also explore jump operations like “[c”, “]c”, “[f”, “]f” to navigate around a source code (class definitions, method definitions, etc.)
You also have some refactorings, like “Rename” (of course, updating references throughout the project’s files) and “Extract” (variable, constant, methods). You can experiment with them by searching for them with “<leader> s k” or using “<leader> c” and then waiting for the available commands (provided by the Neovim plugin “which-ley”, automatically configured by LazyVim).
That’s all for this post; stay tuned for future blog posts, where we’ll cover:
Let’s continue the Sway window manager (in Arch Linux) series I started in my previous post and continued in the other post.
Screenshots
We can use “grimshot”, part of sway-contrib, to take screenshots, which requires the main program for performing the actual screenshot, “grim”.
1
sudo pacman-Ssway-contrib grim
By default, such utilities are installed in “/usr/share/sway-contrib”, which is not part of the PATH. So, put that directory in the PATH environment variable or prefix the call with the full path.
This is the first part of a few tutorials on Java development 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 the Java LSP up and running in Neovim.
You need Java installed (possibly 21), while Maven is optional.
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:
Shell
1
NVIM_APPNAME=lazyvim-java nvim
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-java”.
I suggest you try to follow the tutorials by manually executing the configuration steps in such a new separate Neovim configuration.
The end of the first part is the branch “first-blog-post”.
To make the tutorial more readable, I will use a few different “light” themes in Neovim instead of the default dark one. Remember that you can temporarily switch the theme with “leader uC”.
A few initial notes
LazyVim comes with autoformatting on save. If you don’t want to disable that in configuration, at least you can use these commands to toggle it during the current session:
“<leader> u f” Toggle Auto Format (Global)
“<leader> u F” Toggle Auto Format (Buffer)
Moreover, by default, LazyVim is configured to replace tabs with spaces. I don’t like such a behavior globally, so I disable it by adding this line to the existing file “config/options.lua”
Lua
1
vim.opt.expandtab=false-- Don't use spaces instead of tabs
If you cloned the above Maven Java example, you can try opening one of its Java files in Neovim:
Without the Java LSP, you only have basic syntax highlighting but no other IDE tooling.
Let’s install the LazyVim “Java Extra”. A LazyVim extra is meant to configure several plugins and configurations with a single mechanism. In this case, it will configure the Java LSP (“jdtls”, the Java LSP provided by Eclipse, implementing all the excellent Eclipse IDE Java development features) and configure 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/java. 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.java”; if not, search for “lang.java” and when you’re on that line, press “x” to install the extra.
You get the feedback about restarting Neovim:
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):
Lua
1
2
3
4
5
6
7
8
9
{
"extras":[
"lazyvim.plugins.extras.lang.java"
],
"news":{
"NEWS.md":"7429"
},
"version":7
}
The idea is to keep this file in the Git repository for your configuration as part of your dotfiles for Neovim.
You can now try and open a Java file from this project.
It will not work the first time because Mason has to install the LSP. So, it would try to start the Java LSP (“jdtls”) before it is fully installed. After you see that Mason has successfully installed “jdtls”, you can restart Neovim.
Of course, you could force the installation of “jdtls” by using the Mason UI, “:Mason”: select “jdtls” and install it.
Alternatively, if you want a fully automated solution that, besides installing all the Neovim plugins, also automatically installs the Java 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:
Lua
1
2
3
4
5
6
7
8
return{
"williamboman/mason.nvim",
opts={
ensure_installed={
"jdtls",
},
},
}
Now, when you start Neovim, “jdtls” will automatically install. Remember that “jdtls” is a big Java JAR, so you might want to check whether Mason has successfully downloaded and installed it or is still installing it through the Mason UI.
It works best if you start Neovim from the root directory of the Maven project (the one containing the “pom.xml”). If you open a Java file from another directory, the configured LSP will still search for a “pom.xml” in the parent directories until it finds one (other valid files are the Gradle and Ant specification files if the project is not based on Maven); the root of a Git repository is also a valid root directory.
The highlighting looks much better, with many more highlighted parts (thanks to Treesitter, which the LazyVim Java Extra includes), and you can see the messages from the Java LSP doing its checks and tasks (including downloading Maven dependencies if they are not already cached):
This is a Maven project, so the Java LSP has to resolve the Maven dependencies. If this is the first time you open this project, you should see messages about downloading Maven dependencies.
When all dependencies have been resolved, and the Java LSP has correctly compiled the sources, you can also see some editor decorations (inlay hints), like the parameter names, when calling a method (of course, those parts are NOT part of the source, but only visual content in the editor):
You can enable/disable inlay hints with “<leader> u h”.
With “<leader> c C” you can also refresh “code lens”; for Java, you get the references to classes and methods:
Hovering support (“K”) allows you to see the Javadoc of the current element, e.g., for String:
Pressing any key will make the pop-up window go away. If you want to scroll the pop-up window, use “Ctrl w w” (switch window), and you can scroll the Javadoc.
You’re ready to develop your Java program using typical IDE tooling, like content assist.
Exiting the “insert mode” automatically triggers Java validation, possibly showing warnings and error markers in the editor.
NOTE: The Jdtls LSP (i.e., how LazyVim configures such an LSP by default) creates an Eclipse workspace in the directory “~/.cache/lazyvim-java/jdtls/” in a subdirectory named after the Maven project, e.g., in this example, “~/.cache/lazyvim-java/jdtls/maven-bank-example”. This is just information since you don’t need to care about the created workspaces, which are meant to be ephemeral.
The example used in this post is an Eclipse project. The LSP detects that and possibly updates the Eclipse metadata files accordingly, e.g., “.classpath”, “.settings” directory, “.project”, etc.). If you start with a Maven project (not Eclipse) since the Java LSP is the one from Eclipse, it will create the above Eclipse metadata files automatically for you.
Interestingly, you could use a plain existing Eclipse project, and the Java LSP would still work in Neovim. For example, this is an Eclipse project (not Maven), again part of my TDD book: https://github.com/LorenzoBettini/assertj-log4j-bank-example. It contains the JARs for Assertj and Log4J, and the “.classpath” refers to the JARs that are included. It works seamlessly in Neovim!
We use mako, a lightweight notification daemon for Wayland, one of the optional software suggested when we installed Sway. We also need “inotify-tools”:
1
sudo pacman-Sinotify-tools mako
The nice thing about mako is that you don’t need to start it manually as a service: the first time a notification is emitted, mako will run automatically.
Let’s try to run the notification command:
1
notify-send"hello"
We see the pop-up in the screen’s top right corner by default.
You can have a look at mako’s manual (5) about its configuration file and where it is searched for:
1
2
3
4
5
6
7
8
9
10
11
12
man 5 mako
NAME
mako - configuration file
DESCRIPTION
The config file is located at <strong>~/.config/mako/config</strong> or at $XDG_CON‐
FIG_HOME/mako/config. Option lines can be specified to configure mako like so:
key=value
Empty lines and lines that begin with # are ignored.
Each time you modify the configuration, you must reload mako by using one of the following commands:
1
killall mako
or
1
makoctl reload
With that example configuration, we can emit a few notifications with different “urgencies”, and see the different colors and positions of the boxes:
1
2
3
4
5
6
7
notify-send-ulow"hello world\!""This is a low urgency message"
notify-send-unormal"hello world\!""This is a normal message"
notify-send-ucritical\
"This is a critical message\!"\
"OK, that was just a demo ;)"
If you use EndeavourOS, you will get notifications about new updates and when a reboot is required after a system update (the latter is a “critical” notification):
This post can be used for Arch Linux and EndeavourOS.
Recently, a change was committed that highly compresses AUR packages before the actual installation. This takes a lot of time: even on a fast machine, installing something like Chrome or Visual Studio (AUR packages) takes even minutes just for the compression phase. Since I typically remove the generated packages in the AUR cache after installation (e.g., “~/.cache/yay”), the compression is entirely useless to me.
To disable compression altogether, you can edit the file “/etc/makepkg.conf” (requires sudo, of course) and change the line:
Shell
1
PKGEXT='.pkg.tar.zst'
into:
Shell
1
PKGEXT='.pkg.tar'
And you’re done! Now, even if the string “Compressing package…” is printed on the screen when installing an AUR package, that is actually a no-op.
If you don’t want to change the system file “/etc/makepkg.conf”, you can create this file in your user home, “~/.config/pacman/makepkg.conf”, whose contents take precedence over the ones of the system file. Just put the line:
It assumes you have already read the first, second, and third posts.
Let’s now use the POM editor to update the version of JUnit (the Maven archetype is based on an old version of JUnit). When we open the “pom.xml” in the editor, we get a pop-up suggesting installing another extension for analyzing dependencies.
Let’s accept that, as done before, without synching. After the extension is installed, we can visit the corresponding entry in the extensions tab, and, as done before, we use the gear icon to add the extension to our “.gitpod.yml”.
We can then click on the bottom status bar’s button corresponding to the extension (see the one in the left corner in the screenshot) to have an analysis report:
Once it’s finished, we can look at the report. For this simple example, we don’t have any vulnerabilities in our dependencies:
Let’s go back to editing the “pom.xml”; by using the code completion, we can select the newer version of JUnit 4:
Let’s select the latest version (at the time of writing, it is 4.13.2) and let the Java LSP rebuild the project. When we update a dependency in the POM, the analyzer seen above automatically performs another analysis (you can see the feedback in the bottom status bar).
Let’s now explore the “Maven” outline:
We can run lifecycle phases (“compile” in the screenshot above) or single plug-in goals (something I don’t find in the Eclipse Maven support). We can also see the dependencies and their transitive dependencies (“hamcrest” is a transitive dependency of JUnit).
The “Dependencies” entry provides a “+” icon to add a dependency by using the UI. A pop-up will appear where you type a part of the dependency, press ENTER, and see some completions. For example, for log4j:
Upon selection, the POM will be updated. We intentionally selected an old version of LOG4J with a known vulnerability issue to show that the Dependency Analyzer we previously installed detects that:
We can undo the modification we made only for demonstration or use a recent version of log4j (version 2).
We can also create new “Favorites” commands (by pressing the “+” it appears when hovering on “Favorites”). This will open a pop-up for letting us insert a Maven command we want to run often.
For example, let’s insert “package -DskipTests=true”. The favorite will be saved into the Git repository in the file “.vscode/settings.json”. We can also manually tweak it, giving it an alias, e.g., “Create JAR without running tests” (note that we can use content assist in the JSON file):
Now, we have the favorite with the given alias that we can run by using the corresponding triangle:
Speaking of language support for the “settings.json” file, I prefer to disable “autosave”, especially with LSP running in the background, which will continuously ask to synchronize the Java project each time you start modifying the POM. Using the content assist, it is easy to find the corresponding entry and disable autosave:
Since I have already blogged about Hyprland a lot, I want to report that Hyprland runs smoothly on this PineBook Pro. I basically reused all my ricing and customizations that I blogged about in my previous posts about Hyprland.
Here are a few screenshots:
That’s all! As I said, this was meant to be a brief report. 🙂
I’m starting a new blog series about Sway, a Wayland Tiling Window Manager (the Wayland version of i3). Though I’ve already blogged about Sway, this post (and a few future ones) are intended as “getting started tutorials”.
I’ll focus on Sway in Arch, in particular, EndeavourOS.
Let’s start by installing EndeavourOS with no graphical environment installed:
Once the installation is finished, let’s log in to a terminal session since we have no Desktop Environment.
Let’s install the main package:
1
sudo pacman-Ssway
The output shows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Sway requires additional setup for privilege escalation. Without this setup,
sway will fail to start with session activation permission failures. Choose one
of the two available options (In alphabetical, not recommended, order):
1. polkit: This will make sway "just work" right after installation but may be
a weightier solution than desired.
2. seatd: Already required as a sway dependency, this is a lighter-weight
solution but requires some user configuration: Enabling the service,
adding your user to the "seat" group, then logging out/in again.
Either option should provide the same functionality/stability. Refer to the
Sway wiki page for information.
Optional dependencies for sway
dmenu: dmenu_path support (used alongside wmenu in default $menu)
foot: Terminal emulator used in the default configuration
i3status: Status line generation
mako: Lightweight notification daemon
polkit: System privilege control. Required if not using seatd service [installed]
swaybg: Wallpaper tool for sway
sway-contrib: Collection of user-contributed scripts for sway
swayidle: Idle management daemon
swaylock: Screen locker
waybar: Highly customizable bar
wmenu: Application launcher used in default config
xorg-xwayland: X11 support
xdg-desktop-portal-gtk: Default xdg-desktop-portal for file picking
The package “polkit” has already been installed (see above), so we should be fine.
Let’s also install “foot” to be able to open a terminal with the default configuration and also “wmenu” and “dmenu” (see the output above about these programs):
1
sudo pacman-Sfoot wmenu demnu
Now, we can start “sway” from the command line.
There’s not much with the default configuration: just the workspace indicator (top-left) and the date and time (top-right), not even a wallpaper (we’ll deal with that in a minute).
We can start a terminal (“foot”) with SUPER+ENTER.
To start an application with the application launcher (by default wmenu/dmenu), for example, “firefox” (if installed) we use SUPER+D and start typing in the prompt appearing in the top left corner; a few letters should be enough til you get to the desired program (and press ENTER to launch it).
Of course, the windows are tiled:
NOTE: the SUPER (i.e., the “Window key”) is the default “mod” modifier for keybindings, but you can change it to something else if you want (e.g., “Alt”).
We can switch workspaces with SUPER+<workspace number>, start other terminals there:
We can focus windows with SUPER+<arrow keys> and move a window to another workspace with SUPER+SHIFT+<workspace number>—and close windows with SUPER+SHIFT+Q.
To move the current window and change its position in the tiling, use SUPER+SHIFT+<arrow keys> (instead of arrow keys, you can also use the H, J, K, and L as in Vim):
Let’s install the package “swaybg” (see the output above; that’s the “Wallpaper tool for sway”):
1
sudo pacman-Sswaybg
Now, let’s reload sway with SUPER+SHIFT+C and…
We have the wallpaper!
It’s time to start customizing the configuration.
Let’s create the directory for the configuration file and start from the default one:
1
2
mkdir-p~/.config/sway
cp/etc/sway/config~/.config/sway/
Now, we can edit the “~/.config/sway/config” file. (note that the file ends with “include /etc/sway/config.d/*”, which properly sets a few environment variables and makes them available to systemd).
The first thing I will customize is the keyboard layout: I have an Italian keyboard, so I have to specify that (the default is an American layout). I’ll add this section somewhere in the config file (e.g., near the comments about other input configurations):
1
2
3
4
5
# right Ctrl to switch
input type:keyboard {
xkb_layout it,us
xkb_options grp:rctrl_toggle
}
This will give me an Italian layout by default, and I can switch to an American layout by pressing the right CTRL.
Save the file, reload with SUPER+SHIFT+C, and experiment with the keyboard layouts.
Let’s change the application launcher, which is not very useful in its current shape. Let’s use the Wayland version of Rofi.
1
sudo pacman-Srofi-wayland
Then, let’s open the Sway config file and change the setting of the $menu as follows:
1
set$menu"rofi -show drun -show-icons"
Reload Sway and now pressing the SUPRT+D will get us a much nicer application launcher (just start typing to filter the entries):
Let’s install a file manager, like Nemo.
1
sudo pacman-Snemo
Then, we can create a shortcut for opening the file manager; let’s open the Sway config file, define a variable for the file manager (it will make it easier in the future to switch to another file manager, for example) and a key binding, e.g., SUPER+SHIFT+ENTER:
1
2
3
4
set$filemanager nemo
...
# Start a filemanager
bindsym$mod+Shift+Returnexec$filemanager
Moreover, I prefer Alacritty as a program for terminal:
1
sudo pacman-Salacritty
Then, we just have to change the “$term” definition in the Sway config file: change the line “set $term foot” to
1
set$term alacritty
Now, we need an Authentication Agent, which pops up a window asking you for a password whenever an app wants to elevate its privileges. I prefer the KDE one:
1
sudo pacman-Spolkit-kde-agent
And start it when Sway starts; so in the Sway configuration file:
1
2
### Autostart applications
exec"/usr/lib/polkit-kde-authentication-agent-1"
Since this is “exec”, not “exec_always”, you need to restart Sway, not simply reload it.
Now, if we run from a terminal a “systemctl” command that needs superuser privileges, we get the pop-up dialog asking for a password:
The configuration file already contains a commented section for locking and screensaver:
Shell
1
2
3
4
5
6
7
8
9
10
11
12
### Idle configuration
#
# Example configuration:
#
# exec swayidle -w \
# timeout 300 'swaylock -f -c 000000' \
# timeout 600 'swaymsg "output * power off"' resume 'swaymsg "output * power on"' \
# before-sleep 'swaylock -f -c 000000'
#
# This will lock your screen after 300 seconds of inactivity, then turn off
# your displays after another 300 seconds, and turn your screens back on when
# resumed. It will also lock your screen before your computer goes to sleep.
So, let’s install the involved programs (also mentioned above when we installed Sway):
1
sudo pacman-Sswayidle swaylock
Uncomment the “exec” command; remember that we need to restart Sway to have that mechanism in action. (Of course, you have to wait for 300 seconds). I’m not covering customization of the lock screen and the like here.
We can also set a key binding to lock the screen manually. I usually use SUPER+L; note that this is already bound as a combination to move on the left window (remember the Vim keybindings above?); so, first, I have to uncomment the corresponding bindings (I uncomment them all because I’m not using them: I prefer arrow keys) and add mine:
1
2
3
4
5
6
7
# lock the screen
bindsym$mod+lexec swaylock-f-c000000
...
#bindsym $mod+$left focus left
#bindsym $mod+$down focus down
#bindsym $mod+$up focus up
#bindsym $mod+$right focus right
Let’s install some of the optional packages suggested above when installing Sway (in particular, the “xorg-xwayland” will allow us to run also X applications):
1
2
3
4
sudo pacman-S\
xorg-xwayland\
xdg-desktop-portal-gtk\
xdg-desktop-portal-wlr
That’s all for this first tutorial part; stay tuned for more to come 🙂
It assumes you have already read the first and second posts.
On the bottom, we can see that there are two warnings on our project; let’s click the icon and see them in the “Problems” tab:
Since this is not a Java project managed by Visual Studio Code but a Maven project, we must fix the warning in the POM.
Let’s assume we want to update our project to use the Java version installed in the Gitpod workspace: Java 11 (we can tell that from the warning, but we could also run “java -version” from a terminal to verify that). We open the POM file and update the corresponding properties of Java 1.7: we change “1.7” to “11”:
As soon as we modify the POM, we get a pop-up: the Java LSP detects a change in the project configuration and offers to synchronize the classpath and rebuild the project. Of course, we accept. We accept that, and after a few seconds, the warnings go away.
Note that our choice leads to creating the settings file for this option. We can choose to rebuild the project automatically (“Always”), and the settings file will be updated accordingly. Of course, it makes sense to store such a file in the Git repository.
We can now create a commit with our changes and push them to GitHub.
Remember that the JSON editor is aware of the corresponding schema, so we can enjoy code completion for the string value:
Let’s now say we want to use Java 17 for our project. The workspace provides Java 11, so we must also have Java 17 installed in the Gitpod workspace.
Let’s modify the POM for Java 17 and rebuild the project. Let’s try to run the main file. The Java application still runs, as we can see from the terminal:
Gitpod workspace uses SDKMAN to provide a few versions of tools like the JDK and uses the version required by the project (in this example, Java 17).
We can list the installed JDK in the terminal (and the current one):
1
2
3
$sdk list java|grep installed
||17.0.9.fx|zulu|installed|17.0.9.fx-zulu
|>>>|11.0.21.fx|zulu|installed|11.0.21.fx-zulu
If we wanted to go for Java 21, we should install that version with SDKMAN, but we wouldn’t want to do that manually each time we open a Gitpod workspace. Moreover, instead of the “Zulu” distribution, we might use the “Temurin” distribution.
The recommended way is to provide a custom Dockerfile for our Gitpod workspace to have full explicit control over the versions of the tools we use; this will be part of the Git repository and live with the code.
So we create in the root of our project the file “.gitpod.Dockerfile,” and we configure SDKMAN for the version of Java we want to install and set as the current (the available versions can be discovered with “sdk list java”):
1
2
3
4
5
6
7
FROM gitpod/workspace-full
USER gitpod
RUN bash-c". /home/gitpod/.sdkman/bin/sdkman-init.sh && \
sdk install java 17.0.9-tem && \
sdk default java 17.0.9-tem"
Then, we refer to this Dockerfile in the “.gitpod.yml”:
YAML
1
2
3
image:
file: .gitpod.Dockerfile
...
As before, we can let Gitpod validate our configuration and start a new workspace with the rebuilt Docker image.
As shown in my previous post on Gitpod, you might want to start from a smaller base image with only the needed tools like Java. That would decrease the time to build the custom Docker image. That is out of the scope of this post.
However, rebuilding the Docker image will be done the first time you start a workspace, and the custom image will be cached.
On the new workspace, we can verify that we are using the Java version we installed and set as default:
OpenJDK 64-Bit Server VM Temurin-17.0.9+9 (build 17.0.9+9, mixed mode, sharing)
Again, we commit our changes (including the new custom Dockerfile) and push them to GitHub.
One could use the same strategy for installing a specific version of Maven through SDKMAN. Maven is also installed in the workspace through SDKMAN.
I want to conclude that this process seems long. Still, once you get familiar with the configuration of Gitpod for Java/Maven projects, for new repositories of the same kind, it is enough to immediately put in the Git repository the “.gitpod.yml” and the “.gitpod.Dockerfile.” You can immediately start coding with Gitpod! 🙂
Remember, though, that the first time, you will still have to wait for the build of your custom Docker image.
I love to manage my dotfiles with Chezmoi, which I highly recommend! In a single Git repository, I have common dotfiles and Window Manager specific (KDE, GNOME, Hyprland, and Sway).
However, I prefer to have my Neovim configuration in another Git repository, separate from my Chezmoi dotfiles. I’ve just started learning Neovim, and I’m not yet 100% sure the configuration I use will be the ultimate one (I use Lazyvim); that’s why I want to keep them separate.
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 for my Neovim configuration 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.
For example, I want my “~/.config/nvim” directory (where Neovim configuration lives) to be populated (and kept up-to-date) with the contents of my GitHub repository “https://github.com/LorenzoBettini/starter” (as I said above, I’m using a fork of the Starter repository of Lazyvim):
INI
1
2
3
4
[".config/nvim"]
type="git-repo"
url="git@github.com:LorenzoBettini/starter.git"
refreshPeriod="1h"
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:
This blog post will describe the new procedure for installing EndeavourOS ARM on a PineBook Pro.
As usual, the instructions can be found here: https://endeavouros.com/endeavouros-arm-install/. Previously, there used to be three possible ways to install the system. Now, if we’re not considering the headless server installation, there’s only one way.
First, download the installation image (“.img.xz”) from the above page. For the PineBook Pro, I downloaded “enosLinuxARM-pbp-latest.img.xz“.
This image must be flashed on the final installation medium. I will install EndeavourOS ARM for PineBook Pro on an SD card in this blog post. The idea is that you then boot the PineBook Pro with such a flashed medium, and the installation procedure will finalize the installation on the same medium; during the textual installation, you specify a few configurations.
Of course, the flashing can be performed on any computer, not necessarily from the PineBook Pro.
The delicate part is ensuring you get the name of the flashing device properly or you wipe a device completely. You can use the command “sudo fdisk -l” to get the list of all the devices.
In my case, the inserted SD card is “/dev/sda“, so I flash the image as follows (again, BE COMPLETELY SURE of the correct device!!!):
Be patient; this will take a few minutes, especially depending on the speed of the SD card.
Then, it’s time to boot the PineBook Pro with the SD inserted.
I’m assuming you already have a boot program that allows you to select the booting device. For example, I have “Tow-Boot”.
At some point, I press ESC to select the booting device:
The textual installation starts.
Remember, it will install the system on the same device you used to boot.
Here are some required information:
Of course, you’ll also be asked for your username and password.
Then, you select the Desktop environment (or no desktop at all):
I selected KDE Plasma. Here’s the summary.
After a few minutes, you should get:
Time to reboot!
Unfortunately, at the first reboot, selecting SD to boot into the installed system brought a failure that no bootable image could be found. However, rebooting and selecting SD again succeeded.
IMPORTANT: as you noted, you have no choice about partitioning and filesystem type: you will get EXT4. To be honest, I never managed to setup BTRFS with the previous EndeavourOS installation anyway.
I could finally land on the newly installed KDE Plasma.
I’d suggest doing some configurations and tweaking, e.g., you need to configure swap since 4 gigabytes of RAM are too few! You could go for a swap file, but I’d recommend using zram as the primary swap.
I hadn’t used Eclipse in Hyprland for a while. It used to work correctly; however, starting from somewhere in version 0.41, something broke, and it’s still broken in the current (at the time of writing) version 0.43.
When I execute Eclipse in Hyprland, i.e., in Wayland mode, the trees in Eclipse, e.g., Package Explorer (but also Project Explorer or the Outline) are displayed correctly until you start expanding the tree or hover with the mouse: the elements of the tree gets corrupted and disappear:
Till the whole tree disappears:
I reported the bug (https://github.com/hyprwm/Hyprland/issues/7829). The bug was closed because it had already been reported: in the beginning, the bug talked about DBeaver, which I didn’t know is an Eclipse-based application: https://github.com/hyprwm/Hyprland/issues/6844. The problem is associated with a previous hack to avoid flickering in the Qt application. Unfortunately, the hack breaks Eclipse-based applications, and it’s still there at the time of writing.
If I want to use Eclipse in Hyprland, I have to run it in X11 mode, i.e., by prefixing its execution with the corresponding environment variable set:
1
env GDK_BACKEND=x11./eclipse
Since I have Hyprland with scaling enabled (1.5) Eclipse in X11 mode (Xwayland) gets pixelated:
To avoid that, as documented in Hyprland, I have to disable XWayland scaling by adding this section in “~/.confgi/hyprland/hypr.conf”:
1
2
3
4
# unscale XWayland
xwayland{
force_zero_scaling=true
}
Now, Eclipse runs in Xwayland without flickering but it’s unreadable to me (after all, it is not scaled):
We can scale it with the environment variable “GDK_SCALE”, but that does not support fractional scaling: set it to 2, and then Eclipse gets too big:
However, I can use another environment variable, “GDK_DPI_SCALE”, which scales text only (not icons; better than nothing!);
I’m using Sway (not as my daily driver) on different computers: PCs and laptops.
For the PCs, I’m using an HDMI monitor. Laptops have different display sizes, e.g., small displays with low resolution and more extensive displays with retina resolution. Thus, I need to set different scaling factors for the different displays.
It’s pretty easy in Sway, and I’ll detail that here.
First, you need to get the information Sway uses to refer to your current monitor:
I want to scale at 1.6 on this computer. Otherwise, I can’t read almost anything.
In “~/.config/sway/config”, I specify scaling for this computer using the name shown above
1
2
# LG GRAM 16
output"LG Display 0x0694 Unknown"scale1.6
Reload the configuration, and now scaling is correctly applied when using this laptop.
On the other laptops (e.g., my Acer Aspire Vero), I repeat the same procedure: get the identifier and add a specific configuration with the identifier; for example, for this other laptop, 1.25 scaling is enough:
1
2
# Acer Vero
output"AU Optronics 0x0C9C Unknown"scale1.25
For HDMI monitors, I want 1.5:
1
2
# HDMI monitor
output"HDMI-A-1"scale1.5
Summarizing, this is the monitor section in my Sway configuration, which automatically sets the desired scale factor according to the computer I’m using:
1
2
3
4
5
6
7
8
9
10
### Output configuration
# HDMI monitor
output"HDMI-A-1"scale1.5
# LG GRAM 16
output"LG Display 0x0694 Unknown"scale1.6
# Acer Vero
output"AU Optronics 0x0C9C Unknown"scale1.25
Of course, you can change many values for each monitor, including resolution and orientation, by specifying the corresponding identifier.
In my case, I only want to change the scaling factor.
The crucial ones are the “qt5ct” and “qt6ct-kde” packages. We’ll use the latter but also install the former for possible old Qt 5 applications, just in case. The “Hack” font is the standard KDE monospace font, and Kvantum is the theme engine. Finally, “breeze” will install the Breeze color schemes we will use in qt6ct.
IMPORTANT: we use the AUR package qt6ct-kde, which is a patched version of “qt6ct”. If you installed packages, as in my previous post on this subject, you’ll have to replace “qt6ct” when installing this AUR package.
Then, we have to set this environment variable in “~/.config/hypr/hyprland.conf” (note that we specify qt5ct, but for Qt 6 applications, qt6ct will be used automatically):
1
2
# For styling
env=QT_QPA_PLATFORMTHEME,qt5ct
Let’s restart Hyprland (I’m assuming “env = QT_QPA_PLATFORM,wayland” is also set).
That’s the standard style of Dolphin, Kate, and Konsole with the default settings:
Let’s open the “Qt6 Settings” application (corresponding to “qt6ct”).
Remember that Qt6 settings will be stored in the file “~/.config/qt6ct/qt6ct.conf”.
First of all, I’m changing the fonts to match the standard ones of KDE:
Remember always to click “Apply” after changing something”.
By restarting the above applications, the fonts now look like in a standard KDE system:
Now, benefitting from the patched qt6ct package, differently from my previous post, we can select the “Breeze” style; similarly, we can select “Breeze Dark (KColorScheme)” in color:
Let’s see the results:
Super! Everything looks great with the above simple setting!
If you look at my previous post without the patched version of “qt6ct”, we had to select the “Breeze Dark” icon to have nice-looking icons in the dark style. Now, we didn’t have to!
Moreover, Kate also automatically uses the dark breeze theme (compare that with the previous post):
Note that you can tweak other settings in qt6ct further.
In particular, you can install other icon packages and select another icon set in qt6ct.
Of course, you could also directly use Kvantum themes, as we saw in my previous post. However, with the patched “qt6ct”, having a nice-looking and consistent theme for KDE applications is much easier.
For example, here I have the workspaces with the following application windows:
Kate (text editor) and terminal (Alacritty)
Dolphin (file manager)
A Firefox window and a Firefox window on GitHub
A Firefox window on YouTube and Thunderbird (email client)
Here’s the Wyabar workspace representation (on the left):
Here I added Google Chrome in the workspace 2:
This is the Waybar module configuration, where the important thing is “{window}” in the “format”. Unfortunately, you must work on defining the rewrite rules and the icon to show as you want. Moreover, these are not icons; they are characters from Nerd fonts:
Probably, your browser will not render the fonts (though you can copy and paste them, and they will be taken correctly). I’m also showing a screenshot of my text editor where the Nerd fonts are rendered correctly:
Of course, you also have a character to be used by default if nothing matches (e.g., a question mark).
Nice feature, isn’t it? 🙂
We use cookies on our website to give you the most relevant experience by remembering your preferences and repeat visits. By clicking “Accept All”, you consent to the use of ALL the cookies. However, you may visit "Cookie Settings" to provide a controlled consent.
This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary cookies are absolutely essential for the website to function properly. These cookies ensure basic functionalities and security features of the website, anonymously.
Cookie
Duration
Description
cookielawinfo-checkbox-analytics
11 months
This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics".
cookielawinfo-checkbox-functional
11 months
The cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional".
cookielawinfo-checkbox-necessary
11 months
This cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary".
cookielawinfo-checkbox-others
11 months
This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other.
cookielawinfo-checkbox-performance
11 months
This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance".
viewed_cookie_policy
11 months
The cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data.
Functional cookies help to perform certain functionalities like sharing the content of the website on social media platforms, collect feedbacks, and other third-party features.
Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.
Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics the number of visitors, bounce rate, traffic source, etc.
Advertisement cookies are used to provide visitors with relevant ads and marketing campaigns. These cookies track visitors across websites and collect information to provide customized ads.