mirror of
https://github.com/ItsDrike/dotfiles.git
synced 2024-12-24 12:14:35 +00:00
Major rewrite: switching back to Arch from NixOS
This commit is contained in:
parent
df585b737b
commit
254181c0fc
111
README.md
111
README.md
|
@ -1,32 +1,16 @@
|
|||
> [!CAUTION]
|
||||
> As of 18th June 2024, I have migrated from Arch to NixOS, rendering this repository archived.
|
||||
>
|
||||
> NixOS is a Linux distribution that allows declaratively defining the entire system and with
|
||||
> the help of some extra tools, such as home-manager, it's possible to declare configurations for
|
||||
> various programs in my home directory in this way too.
|
||||
>
|
||||
> This allows me to have all of my system configuration in a single repository from which I can
|
||||
> completely reproduce this system on any computer, down to specific versions of every installed
|
||||
> program / dependency. For obvious reasons, this is far superior to the installation scripts in
|
||||
> this repository.
|
||||
>
|
||||
> If you wish to take a look at my NixOS configuration, you can find the repository here:
|
||||
>
|
||||
> - <https://github.com/ItsDrike/nixdots>
|
||||
> - <https://git.itsdrike.com/ItsDrike/nixdots> (mirror)
|
||||
|
||||
# Dotfiles
|
||||
|
||||
Welcome to my personal dotfiles repository! Simply put, this is a complete collection of my system configuration files,
|
||||
mostly just here for my personal use, but of course, you're free to take anything you like (as long as you follow the
|
||||
license).
|
||||
Welcome to my personal dotfiles repository! Simply put, this is a complete
|
||||
collection of my system configuration files, mostly just here for my personal
|
||||
use, but of course, you're free to take anything you like (as long as you follow
|
||||
the [license](./LICENSE).
|
||||
|
||||
## Images
|
||||
|
||||
What everyone is here for!
|
||||
|
||||
**My WM and EWW bar**
|
||||
https://user-images.githubusercontent.com/20902250/202879948-f5d79f70-72ff-4cae-97aa-da9a863ac688.mp4
|
||||
<https://user-images.githubusercontent.com/20902250/202879948-f5d79f70-72ff-4cae-97aa-da9a863ac688.mp4>
|
||||
|
||||
**Prompt timing showcase**
|
||||
![image](https://user-images.githubusercontent.com/20902250/202880140-78dc3f65-ea5d-4155-819b-39bd30d2b31e.png)
|
||||
|
@ -39,55 +23,75 @@ https://user-images.githubusercontent.com/20902250/202879948-f5d79f70-72ff-4cae-
|
|||
|
||||
## Features
|
||||
|
||||
- Full fledged ZSH configuration without relying on oh-my-zs
|
||||
- oh-my-zsh configuration is also supported, but it is off by default, adjust [`.zshrc`](./home/.config/zsh/.zshrc)
|
||||
to enable it
|
||||
- While you can enable the omz support, it's not at all necessary, as my configuration already handles most of the basic config, and also adds a ton of cool features
|
||||
- Fully custom terminal prompt with a lot of neat features, such as CWD shortening, showing git status, seeing how long
|
||||
a command ran for, and showing non-zero exit codes [prompt](./home/.config/shell/prompt)
|
||||
- A ton of neat and helpful [aliases](./home/.config/shell/aliases) and [functions](./home/.config/shell/functions)
|
||||
(probably too many for most people, you should adjust these to your needs)
|
||||
- Full fledged ZSH configuration without relying on oh-my-zsh
|
||||
- Fully custom terminal prompt with a lot of neat features, such as CWD
|
||||
shortening, showing git status, seeing how long a command ran for, showing
|
||||
non-zero exit codes, ... [prompt](./home/.config/shell/prompt)
|
||||
- A ton of neat and helpful [aliases](./home/.config/shell/aliases) and
|
||||
[functions](./home/.config/shell/functions) (probably too many for most
|
||||
people, you should adjust these to your needs)
|
||||
- Sensible pre-defined environment variables, allowing for
|
||||
- Colorful man pages using `LESS_TERMCAP`, or if `bat` is installed, using it as `MANPAGER` directly
|
||||
- XDG user directory related variables, making programs use the proper directories, avoiding clutter in `$HOME`
|
||||
- Colorful man pages using `LESS_TERMCAP`, or if `bat` is installed, using it
|
||||
as `MANPAGER` directly
|
||||
- XDG user directory related variables, making programs use the proper
|
||||
directories, avoiding clutter in `$HOME`
|
||||
- Tons of handy scripts for automatic common tasks:
|
||||
- [`incremental-backup`](./root/usr/local/bin/incremental-backup): Simple and minimalistic way to utilize rsync for
|
||||
fast and efficient backups (utilizing hard-links), for any directories, or even for the entire system.
|
||||
- [`auto-chroot`](./root/usr/local/bin/auto-chroot): Quick way to chroot into any accesible linux system, without
|
||||
typing the repetetive mount/umount commands. Allows for selecting user and shell to be used.
|
||||
- [`tamper-check`](./root/usr/local/bin/tamper-check): Script that uses checksums to verify that contents of
|
||||
specified system-critical files haven't changed (be aware that they will obviously change if they're updated)
|
||||
- [`gh-notification`](./home/.local/bin/scripts/gui/gh-notification): Script expected to be ran as cron-job every
|
||||
few minutes, checking for new github notifications using github CLI (requies meiji163/gh-notify gh-cli extension)
|
||||
and sending them out as actual desktop notifications.
|
||||
- [`brightness`](./home/.local/bin/scripts/gui/brightness): Script to quickly change the screen brightness
|
||||
- [`setbg`](./home/.local/bin/scripts/gui/setbg): Simple way to pick a background to be used (both for X11 and
|
||||
Wayland)
|
||||
- Tons of other things! The list is just way too long, check the rest yourself! [system
|
||||
scripts](./root/usr/local/bin), [user scripts](./home/.local/bin)
|
||||
- [`incremental-backup`](./root/usr/local/bin/incremental-backup): Simple and
|
||||
minimalistic way to utilize rsync for fast and efficient backups (utilizing
|
||||
hard-links), for any directories, or even for the entire system.
|
||||
- [`btrfs-backup`](./root/usr/local/bin/btrfs-backup): Simple yet very
|
||||
powerful script to manage btrfs snapshots. I recommend using this in a cron
|
||||
job for taking automatic snapshots.
|
||||
- [`auto-chroot`](./root/usr/local/bin/auto-chroot): Quick way to chroot into
|
||||
any accesible linux system, without typing the repetetive mount/umount
|
||||
commands. Allows for selecting user and shell to be used.
|
||||
- [`tamper-check`](./root/usr/local/bin/tamper-check): Script that uses
|
||||
checksums to verify that contents of specified system-critical files haven't
|
||||
changed (be aware that they will obviously change if they're updated)
|
||||
- [`gh-notification`](./home/.local/bin/scripts/gui/gh-notification): Script
|
||||
expected to be ran as cron-job every few minutes, checking for new github
|
||||
notifications using github CLI (requies meiji163/gh-notify gh-cli extension)
|
||||
and sending them out as actual desktop notifications.
|
||||
- [`brightness`](./home/.local/bin/scripts/gui/brightness): Script to quickly
|
||||
change the screen brightness
|
||||
- [`setbg`](./home/.local/bin/scripts/gui/setbg): Simple way to pick a
|
||||
background to be used (both for X11 and Wayland)
|
||||
- Tons of other things! The list is just way too long, check the rest
|
||||
yourself! [system scripts](./root/usr/local/bin), [user
|
||||
scripts](./home/.local/bin)
|
||||
|
||||
On top of just configurations, this repository also includes a
|
||||
[`guides/`](./guides/) directory with a bunch of guide posts that can help you
|
||||
set up arch from ground up, or set up specific things after installation.
|
||||
|
||||
## Installation
|
||||
|
||||
Clone this repository anywhere you like
|
||||
|
||||
```bash
|
||||
git https://github.com/ItsDrike/dotfiles
|
||||
```
|
||||
|
||||
If you don't want to use git (running straight from newly installed OS), you can even use `curl`:
|
||||
If you don't want to use git (running straight from newly installed OS), you can
|
||||
even use `curl`:
|
||||
|
||||
```bash
|
||||
curl -LJO https://github.com/ItsDrike/dotfiles/tarball/main
|
||||
```
|
||||
|
||||
And extract from `.tar.gz` archive with: `tar xvf [archive name]`
|
||||
|
||||
## Attribution
|
||||
|
||||
The open-source community has an incredible amount of resources that people have freely provided to others and we all
|
||||
depend on these projects in many ways. This collection of configuration files is no exception, and while many of the
|
||||
scripts and configuration files are my own, many others were partially, or even fully taken from other open-sourced
|
||||
repositories like this.
|
||||
The open-source community has an incredible amount of resources that people have
|
||||
freely provided to others and we all depend on these projects in many ways. This
|
||||
collection of configuration files is no exception, and while many of the scripts
|
||||
and configuration files are my own, many others were partially, or even fully
|
||||
taken from other open-sourced repositories like this.
|
||||
|
||||
For that reason, we'd like to thank all of these communities and projects for keeping their content open and available
|
||||
to everyone, but most notably we'd like to thank and reference the significant projects that allowed this repository to
|
||||
For that reason, we'd like to thank all of these communities and projects for
|
||||
keeping their content open and available to everyone, but most notably we'd like
|
||||
to thank and reference the significant projects that allowed this repository to
|
||||
be as amazing as it is now:
|
||||
|
||||
- [Luke Smith's dotfiles/voidrice](https://github.com/LukeSmithxyz/voidrice)
|
||||
|
@ -95,3 +99,6 @@ be as amazing as it is now:
|
|||
- [Brodie Robertson's scripts](https://github.com/BrodieRobertson/scripts)
|
||||
- [Derek Taylor's dotfiles](https://gitlab.com/dwt1/dotfiles)
|
||||
- [Mihai Fufezan's dotfiles](https://github.com/fufexan/dotfiles)
|
||||
- Other sources that I followed from my NixOS configuration and ported over,
|
||||
these are listed in my [NixOS dotfiles](https://github.com/ItsDrike/nixdots)
|
||||
readme
|
||||
|
|
367
guides/01_INSTALLATION.md
Normal file
367
guides/01_INSTALLATION.md
Normal file
|
@ -0,0 +1,367 @@
|
|||
# Installation
|
||||
|
||||
This installation guide will walk you through the process of setting up Arch
|
||||
Linux, getting you from live cd to a working OS.
|
||||
|
||||
This guide is written primarily as a reference for myself, but it can certainly
|
||||
be a useful resource for you too, if you want to achieve a similar setup.
|
||||
|
||||
This guide includes steps for full disk encryption, and sets up the system with
|
||||
some basic tools and my zsh configuration.
|
||||
|
||||
## Partitioning
|
||||
|
||||
First thing we will need to do is set up partitions. To do so, I recommend using
|
||||
`fdisk`. Assuming you have a single-disk system, you will want to create 3
|
||||
partitions:
|
||||
|
||||
- EFI (1 GB)
|
||||
- Swap (same size as your RAM, or more)
|
||||
- Data (rest)
|
||||
|
||||
The swap partition is optional, however I do recommend creating it (instead of
|
||||
using a swap file), as it will allow you to hibernate your machine.
|
||||
|
||||
> [!NOTE]
|
||||
> Don't forget to also set the type for these partitions (`t` command in `fdisk`).
|
||||
>
|
||||
> - EFI partition type: EFI System (1)
|
||||
> - Swap partition type: Linux swap (19)
|
||||
> - Data partition type: Linux filesystem (20)
|
||||
|
||||
### File-Systems
|
||||
|
||||
Now we'll to create file systems on these partitions, and give them disk labels:
|
||||
|
||||
```bash
|
||||
mkfs.fat -F 32 /dev/sdX1
|
||||
fatlabel /dev/sdX1 EFI
|
||||
|
||||
mkswap -L SWAP /dev/diskX2
|
||||
|
||||
cryptsetup luksFormat /dev/sdX3 --label CRYPTFS
|
||||
cryptsetup open /dev/disk/by-label/CRYPTFS crypfs
|
||||
mkfs.btrfs -L FS /dev/mapper/cryptfs
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> For the LUKS encrypted partitions, I'd heavily recommend that you back up the
|
||||
> LUKS headers in case of a partial drive failure, so that you're still able to
|
||||
> recover your remaining data. To do this, you can use the following command:
|
||||
>
|
||||
> ```bash
|
||||
> cryptsetup luksHeaderBackup /dev/device --header-backup-file /mnt/backup/file.img
|
||||
> ```
|
||||
|
||||
### BTRFS Subvolumes
|
||||
|
||||
Now we will split our btrfs partition into the following subvolumes:
|
||||
|
||||
- root: The subvolume for `/`.
|
||||
- data: The subvolume for `/data`, containing my personal files, which should be
|
||||
and backed up.
|
||||
- snapshots: A subvolume that will be used to store snapshots (backups) of the
|
||||
other subvolumes
|
||||
|
||||
```bash
|
||||
mount /dev/mapper/cryptfs /mnt
|
||||
btrfs subvolume create /mnt/root
|
||||
btrfs subvolume create /mnt/data
|
||||
btrfs subvolume create /mnt/snapshots
|
||||
umount /mnt
|
||||
```
|
||||
|
||||
### Mount the partitions and subvolumes
|
||||
|
||||
<!-- markdownlint-disable MD028 -->
|
||||
|
||||
> [!NOTE]
|
||||
> Even though we're specifying the `compress` flag in the mount options of each
|
||||
> btrfs subvolume, somewhat misleadingly, you can't actually use different
|
||||
> compression levels for different subvolumes. Btrfs will share the same
|
||||
> compression level across the whole partition, so it's pointless to attempt to
|
||||
> set different values here.
|
||||
|
||||
> [!NOTE]
|
||||
> You may have seen others use btrfs options such as `ssd`, `discard=async` and
|
||||
> `space_cache=v2`. These are all default (with the `ssd` being auto-detected),
|
||||
> so specifying them is pointless now.
|
||||
|
||||
<!-- markdownlint-enable MD028 -->
|
||||
|
||||
```bash
|
||||
mount -o subvol=root,compress=zstd:3,noatime /dev/mapper/cryptfs /mnt
|
||||
mount --mkdir -o subvol=home,compress=zstd:3,noatime /dev/mapper/cryptfs /mnt/data
|
||||
mount --mkdir -o subvol=snapshots,compress=zstd:3,noatime /dev/mapper/cryptfs /mnt/snapshots
|
||||
mount --mkdir -o compress=zstd:3,noatime /dev/mapper/cryptfs /mnt/.btrfs
|
||||
|
||||
mount --mkdir /dev/disk/by-label/EFI /mnt/efi
|
||||
mkdir /mnt/efi/arch
|
||||
mount --mkdir --bind /mnt/efi/arch /mnt/boot
|
||||
|
||||
swapon /dev/disk/by-label/SWAP
|
||||
```
|
||||
|
||||
## Base installation
|
||||
|
||||
```bash
|
||||
reflector --save /etc/pacman.d/mirrorlist --latest 10 --protocol https --sort rate
|
||||
pacstrap -K /mnt base linux linux-firmware linux-headers amd-ucode # or intel-ucode
|
||||
genfstab -U /mnt >> /mnt/etc/fstab
|
||||
arch-chroot /mnt
|
||||
```
|
||||
|
||||
Configure essentials
|
||||
|
||||
```bash
|
||||
pacman -S git btrfs-progs neovim
|
||||
ln -sf /usr/share/zoneinfo/CET /etc/localtime
|
||||
hwclock --systohc
|
||||
sed -i 's/^#en_US.UTF-8/en_US.UTF-8/g' /etc/locale.gen
|
||||
echo "LANG=en_US.UTF-8" > /etc/locale.conf
|
||||
locale-gen
|
||||
echo "pc" > /etc/hostname
|
||||
passwd
|
||||
```
|
||||
|
||||
## Basic configuration
|
||||
|
||||
Clone my dotfiles and run the install script
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/ItsDrike/dotfiles ~/dots
|
||||
cd ~/dots
|
||||
./install_root.sh
|
||||
```
|
||||
|
||||
Exit and reenter chroot, this time into zsh shell
|
||||
|
||||
```bash
|
||||
exit
|
||||
arch-chroot /mnt zsh
|
||||
```
|
||||
|
||||
Create non-privileged user
|
||||
|
||||
```bash
|
||||
useradd itsdrike
|
||||
usermod -aG wheel itsdrike
|
||||
install -o itsdrike -g itsdrike -d /home/itsdrike
|
||||
passwd itsdrike
|
||||
chsh -s /usr/bin/zsh itsdrike
|
||||
su -l itsdrike # press q or esc in the default zsh options
|
||||
```
|
||||
|
||||
Setup user account
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/ItsDrike/dotfiles ~/dots
|
||||
cd ~/dots
|
||||
./install_user.sh
|
||||
```
|
||||
|
||||
Exit (logout) the user and relogin, this time into configured zsh shell
|
||||
|
||||
```bash
|
||||
exit
|
||||
su -l itsdrike
|
||||
```
|
||||
|
||||
Install LazyVim
|
||||
|
||||
```bash
|
||||
git clone https://github.com/ItsDrike/lazyvim ~/.config/nvim
|
||||
```
|
||||
|
||||
## Fstab adjustments
|
||||
|
||||
Finally, we'll want to make some slight modifications to `/etc/fstab` file, so
|
||||
that we're using labels instead of UUIDs to mount our devices and also fix the
|
||||
permissions for the EFI mount-point (the fmask & dmask options), as by default,
|
||||
they're way too permissive. This is how I like to structure my fstab:
|
||||
|
||||
<!-- markdownlint-disable MD013 -->
|
||||
|
||||
```text
|
||||
# Static information about the filesystems.
|
||||
# See fstab(5) for details.
|
||||
#
|
||||
# <file system> <dir> <type> <options> <dump> <pass>
|
||||
|
||||
# region: Physical partitions
|
||||
|
||||
# /dev/nvme1n1p1 LABEL=EFI UUID=A34B-A020
|
||||
/dev/disk/by-label/EFI /efi vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 2
|
||||
|
||||
# /dev/nvme1n1p2 LABEL=SWAP UUID=d262a2e5-a1a3-42b1-ac83-18639f5e8f3d
|
||||
/dev/disk/by-label/SWAP none swap defaults 0 0
|
||||
|
||||
# endregion
|
||||
# region: BTRFS Subvolumes
|
||||
|
||||
# /dev/mapper/cryptfs LABEL=FS UUID=bffc7a62-0c7e-4aa9-b10e-fd68bac477e0
|
||||
/dev/mapper/cryptfs / btrfs rw,noatime,compress=zstd:1,subvol=/root 0 1
|
||||
/dev/mapper/cryptfs /data btrfs rw,noatime,compress=zstd:1,subvol=/data 0 2
|
||||
/dev/mapper/cryptfs /snapshots btrfs rw,noatime,compress=zstd:1,subvol=/snapshots 0 2
|
||||
/dev/mapper/cryptfs /.btrfs btrfs rw,noatime,compress=zstd:1 0 2
|
||||
|
||||
# endregion
|
||||
# region: Bind mounts
|
||||
|
||||
# Write kernel images to /efi/arch, not directly to efi system partition (esp), to avoid conflicts when dual booting
|
||||
/efi/arch /boot none rw,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro,bind 0 0
|
||||
|
||||
# endregion
|
||||
```
|
||||
|
||||
<!-- markdownlint-enable MD013 -->
|
||||
|
||||
## Ask for LUKS password from initramfs
|
||||
|
||||
Ask for encryption password of the root partition in early userspace (only
|
||||
relevant if you're using LUKS encryption), you'll also need to set cryptdevice
|
||||
kernel parameter, specifying the device that should be unlocked here, and the
|
||||
device mapping name. (shown later)
|
||||
|
||||
```bash
|
||||
# Find the line with HOOKS=(...)
|
||||
# Add `keyboard keymap` after `autodetect` (if these hooks are already there,
|
||||
# just keep them, but make sure they're after `autodetect`).
|
||||
# Lastly add `encrypt` before `filesystems`.
|
||||
nvim /etc/mkinitcpio.conf
|
||||
```
|
||||
|
||||
This will configure `mkinitcpio` to build support for the keyboard input, and
|
||||
for decrypting LUKS devices from within the initial ramdisk environment.
|
||||
|
||||
If you wish, you can also follow the instructions below to auto-enable numlock:
|
||||
|
||||
```bash
|
||||
sudo -u itsdrike paru -S mkinitcpio-numlock
|
||||
# Go to HOOKS and add `numlock` after `keyboard` in:
|
||||
nvim /etc/mkinitcpio.conf
|
||||
```
|
||||
|
||||
Now regenerate the initial ramdisk environment image:
|
||||
|
||||
```bash
|
||||
mkinitcpio -P
|
||||
```
|
||||
|
||||
## Configure systemd-boot bootloader
|
||||
|
||||
> [!NOTE]
|
||||
> If you wish to use another boot loader (like GRUB), just follow the Arch Wiki.
|
||||
> This guide will only cover systemd-boot
|
||||
|
||||
### Make sure you're using UEFI
|
||||
|
||||
As a first step, you will want to confirm that you really are on a UEFI system.
|
||||
If you're using any recent hardware, this is very likely the case. Nevertheless,
|
||||
let's check and make sure:
|
||||
|
||||
```bash
|
||||
bootctl status
|
||||
```
|
||||
|
||||
Make sure the `Firmware` is reported as `UEFI`.
|
||||
|
||||
If you're still using BIOS instead of UEFI, you should check the wiki for
|
||||
instructions on how to set up systemd-boot or choose a different boot manager,
|
||||
that is more suited for BIOS firmware.
|
||||
|
||||
### Install systemd-boot
|
||||
|
||||
Install systemd-boot to the EFI system partition (ESP)
|
||||
|
||||
```bash
|
||||
bootctl --esp-path=/efi install
|
||||
# This might report a warning about permissions for the /efi mount point,
|
||||
# these were addressed in the fstab file above (changed fmask and dmask),
|
||||
# if you copied those to your fstab, the permissions will be fixed after reboot
|
||||
```
|
||||
|
||||
Add boot menu entries
|
||||
(Note that we're using LABEL= for cryptdevice, for which `udev` must be before
|
||||
the `encrypt` hook in mkinitcpio `HOOKS`. This should however be the case by default.
|
||||
If you wish, you can also use UUID= or just /dev/XYZ here)
|
||||
|
||||
Create a new file - `/efi/loader/entries/arch.conf`, with:
|
||||
|
||||
```bash
|
||||
title Arch Linux
|
||||
sort-key 0
|
||||
linux /arch/vmlinuz-linux
|
||||
initrd /arch/amd-ucode.img
|
||||
initrd /arch/initramfs-linux.img
|
||||
options cryptdevice=LABEL=CRYPTFS:cryptfs:allow-discards
|
||||
options root=/dev/mapper/cryptfs rootflags=subvol=/root
|
||||
options rw loglevel=3
|
||||
```
|
||||
|
||||
And finally configure loader - `/efi/loader/loader.conf` (overwrite the contents):
|
||||
|
||||
```bash
|
||||
default arch-hyprland.conf
|
||||
timeout 4
|
||||
console-mode auto
|
||||
editor yes
|
||||
auto-firmware yes
|
||||
beep no
|
||||
```
|
||||
|
||||
## Reboot
|
||||
|
||||
Take a deep breath.
|
||||
|
||||
```bash
|
||||
exit # go back to live iso (exit chroot)
|
||||
reboot
|
||||
```
|
||||
|
||||
## Post-setup
|
||||
|
||||
Log in as an unpriviledged user, and:
|
||||
|
||||
Enable Network Time Protocol (time synchronization)
|
||||
|
||||
```bash
|
||||
sudo timedatectl set-ntp true
|
||||
timedatectl status
|
||||
```
|
||||
|
||||
Connect to a wifi network
|
||||
|
||||
```bash
|
||||
nmtui
|
||||
```
|
||||
|
||||
## Graphical User Interface
|
||||
|
||||
Finally, you can run the `install_gui.sh` script in my dotfiles, to get all of
|
||||
the packages necessary for a proper graphical experience with Hyprland WM and a
|
||||
bunch of applications/toolings that I like to use.
|
||||
|
||||
This final script is definitely the most opinionated one and you might want to
|
||||
make adjustments to it, depending on your preferences.
|
||||
|
||||
## We're done
|
||||
|
||||
If you got this far, good job! You should now be left with a fully functional
|
||||
Arch Linux system, ready for daily use.
|
||||
|
||||
That said, you might find some of the other guides helpful if you wish to tinker
|
||||
some more:
|
||||
|
||||
- If you have more encrypted partitions than just root, you should check out:
|
||||
[automounting other encrypted
|
||||
partitions](./02_AUTOMOUNTING_ENCRYPTED_PARTITIONS.md).
|
||||
- You may be also interested in [setting up secure boot](./04_SECURE_BOOT.md).
|
||||
- Having your encrypted root partition unlock automatically without compromising
|
||||
on safety through [tpm unlocking](./06_TPM_UNLOCKING.md).
|
||||
- The [theming guide](./99_THEMING.md), explaining how to configure qt, gtk,
|
||||
cursor and fonts correctly.
|
||||
- Setting up a display manager (DM) with optional automatic login: [greetd
|
||||
guide](./99_GREETD.md)
|
||||
- On laptops, you should check the [battery optimizations
|
||||
guide](./99_BATTERY_OPTIMIZATIONS.md)
|
138
guides/02_AUTOMOUNTING_ENCRYPTED_PARTITIONS.md
Normal file
138
guides/02_AUTOMOUNTING_ENCRYPTED_PARTITIONS.md
Normal file
|
@ -0,0 +1,138 @@
|
|||
# Auto-mounting other encrypted partitions
|
||||
|
||||
If you've set up multiple encrypted partitions (a common reason to do so is
|
||||
having multiple drives), you will likely want to have these other partitions
|
||||
mounted automatically after the root partition, during the boot process.
|
||||
|
||||
> [!TIP]
|
||||
> You can safely skip this guide if you only have a single encrypted partition
|
||||
> (with the root).
|
||||
|
||||
## /etc/crypttab
|
||||
|
||||
Obviously, with encrypted partitions, you can't simply specify the mounting
|
||||
instructions into your `/etc/fstab`, instead, there is a special file designed
|
||||
precisely for this purpose: `/etc/crypttab`. Just like with `fstab`, systemd
|
||||
will read `crypttab` during boot and attempt to mount the entries inside of it.
|
||||
|
||||
From here, you can add entries for mounting your encrypted partitions, like so:
|
||||
|
||||
```txt
|
||||
# Configuration for encrypted block devices.
|
||||
# See crypttab(5) for details.
|
||||
|
||||
# NOTE: Do not list your root (/) partition here, it must be set up
|
||||
# beforehand by the initramfs (/etc/mkinitcpio.conf).
|
||||
|
||||
# <name> <device> <password> <options>
|
||||
cryptdata LABEL=DATA none discard
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> The `discard` option is specified to enable TRIM on SSDs, which should improve
|
||||
> their lifespan. It is not necessary if you're using an HDD.
|
||||
|
||||
The `<name>` option specifies the name of the decrypted mapper device, so in
|
||||
this case, the decrypted device would be in `/dev/mapper/cryptdata`. We can then
|
||||
add mounting instructions into `/etc/fstab`, that work with this mapper device.
|
||||
|
||||
Specifying a partition in here will result in you being prompted for a
|
||||
decryption password each time during boot. If you only have one encrypted
|
||||
partition like this, and your root partition isn't encrypted, this will be
|
||||
sufficient for you.
|
||||
|
||||
## Key files
|
||||
|
||||
That said, if you have multiple encrypted partitions, or your root partition is
|
||||
encrypted too, you might find it pretty annoying to have to enter a password for
|
||||
each of your encrypted partitions every time.
|
||||
|
||||
For this reason, crypttab includes the `<password>` option, which we originally
|
||||
left as `none`. We can use this field to specify a path to a "key file". This is
|
||||
basically just a file that holds the encryption password.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Storing the decryption password in a key file like this can only be done
|
||||
> safely if that key file is stored on another encrypted partition, which we
|
||||
> decrypted in another way (usually by being prompted for the password).
|
||||
>
|
||||
> In this example, we'll be storing the key files in `/etc/secrets`, which is
|
||||
> safe as our root partition is encrypted.
|
||||
|
||||
LUKS encryption has support for having multiple keys for the same parition.
|
||||
We'll utilize this support and add 2nd key slot to all of the partitions that we
|
||||
wish to auto-mount.
|
||||
|
||||
```bash
|
||||
mkdir -p /etc/secrets
|
||||
dd if=/dev/random bs=4096 count=1 of=/etc/secrets/keyFile-data.bin
|
||||
chmod -R 400 /etc/secrets
|
||||
chmod 700 /etc/secrets
|
||||
```
|
||||
|
||||
The bs argument signifies a block size (in bits), so this will create 4096-bit keys.
|
||||
|
||||
Now we can add this key into our LUKS encrypted data partition:
|
||||
|
||||
```bash
|
||||
cryptsetup luksAddKey /dev/disk/by-label/DATA --new-keyfile /etc/secrets/keyFile-data.bin
|
||||
```
|
||||
|
||||
Finally, we'll modify the `/etc/crypttab` record and add our new keyfile as the
|
||||
password for this partition:
|
||||
|
||||
```txt
|
||||
# Configuration for encrypted block devices.
|
||||
# See crypttab(5) for details.
|
||||
|
||||
# NOTE: Do not list your root (/) partition here, it must be set up
|
||||
# beforehand by the initramfs (/etc/mkinitcpio.conf).
|
||||
|
||||
# <name> <device> <password> <options>
|
||||
cryptdata LABEL=DATA /etc/secrets/keyFile-data.bin discard
|
||||
```
|
||||
|
||||
### /etc/fstab
|
||||
|
||||
While the crypttab file opens the encrypted block devices and creates the mapper
|
||||
interfaces for them, to mount those to a concrete directory, we still use
|
||||
/etc/fstab. Below is the /etc/fstab that I use on my system:
|
||||
|
||||
<!-- markdownlint-disable MD010 MD013 -->
|
||||
|
||||
```text
|
||||
# Static information about the filesystems.
|
||||
# See fstab(5) for details.
|
||||
|
||||
# <file system> <dir> <type> <options> <dump> <pass>
|
||||
|
||||
# region: Physical partitions
|
||||
|
||||
# /dev/nvme0n1p2 LABEL=SWAP UUID=d262a2e5-a1a3-42b1-ac83-18639f5e8f3d
|
||||
/dev/disk/by-label/SWAP none swap defaults 0 0
|
||||
|
||||
# /dev/nvme0n1p1 LABEL=EFI UUID=44E8-EB26
|
||||
/dev/disk/by-label/EFI /efi vfat rw,relatime,fmask=0137,dmask=0027,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 2
|
||||
|
||||
# endregion
|
||||
# region: BTRFS subvolumes on /dev/disk/by-label/ARCH (decrypted from ARCH_LUKS)
|
||||
|
||||
# /dev/mapper/cryptfs LABEL=ARCH UUID=bffc7a62-0c7e-4aa9-b10e-fd68bac477e0
|
||||
/dev/mapper/cryptfs / btrfs rw,noatime,compress=zstd:1,ssd,space_cache=v2,subvol=/@ 0 1
|
||||
/dev/mapper/cryptfs /home btrfs rw,noatime,compress=zstd:1,ssd,space_cache=v2,subvol=/@home 0 1
|
||||
/dev/mapper/cryptfs /var/log btrfs rw,noatime,compress=zstd:2,ssd,space_cache=v2,subvol=/@log 0 1
|
||||
/dev/mapper/cryptfs /var/cache btrfs rw,noatime,compress=zstd:3,ssd,space_cache=v2,subvol=/@cache 0 1
|
||||
/dev/mapper/cryptfs /tmp btrfs rw,noatime,compress=no,ssd,space_cache=v2,subvol=/@tmp 0 1
|
||||
/dev/mapper/cryptfs /data btrfs rw,noatime,compress=zstd:5,ssd,space_cache=v2,subvol=/@data 0 2
|
||||
/dev/mapper/cryptfs /.btrfs btrfs rw,noatime,ssd,space_cache=v2 0 2 # btrfs root
|
||||
|
||||
# endregion
|
||||
# region: Bind mounts
|
||||
|
||||
# Write kernel images to /efi/arch, not directly to efi system partition (esp), to avoid conflicts when dual booting
|
||||
/efi/arch-1 /boot none rw,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro,bind 0 0
|
||||
|
||||
# endregion
|
||||
```
|
||||
|
||||
<!-- markdownlint-enable MD010 MD013 -->
|
205
guides/03_UNIFIED_KERNEL_IMAGES.md
Normal file
205
guides/03_UNIFIED_KERNEL_IMAGES.md
Normal file
|
@ -0,0 +1,205 @@
|
|||
# Unified Kernel Images (UKI) booting
|
||||
|
||||
A Unified Kernel Image is a single executable (`.efi` file), which can be
|
||||
booted directly from UEFI firmware, or be automatically sourced by boot loaders
|
||||
with no extra configuration.
|
||||
|
||||
> [!NOTE]
|
||||
> If you're still using BIOS, you will not be able to set up UKIs, they require
|
||||
> UEFI.
|
||||
|
||||
A UKI will include:
|
||||
|
||||
- a UEFI stub loader like (systemd-stub)
|
||||
- the kernel command line
|
||||
- microcode
|
||||
- an initramfs image
|
||||
- a kernel image
|
||||
- a splash screen
|
||||
|
||||
The most common reason why you might want to use UKIs is secure boot. That's
|
||||
because a UKI is something that can be signed and represents an immutable
|
||||
executable used for booting into your system.
|
||||
|
||||
This is good, because with a standalone bootloader, you would be allowed you to
|
||||
edit the kernel parameters, or even change the kernel image by editing the
|
||||
configuration inside of the (unencrypted) EFI partition. This is obviously
|
||||
dangerous, and we don't want to allow this.
|
||||
|
||||
## Define kernel command line
|
||||
|
||||
Since UKI contains the kernel command line, we will need to define it so that
|
||||
when the image is being built, it can pick it up.
|
||||
|
||||
This is a crucial step especially when you have encryption set up, as without
|
||||
it, the kernel wouldn't know what root partition to use.
|
||||
|
||||
To set this up, we will use `/etc/kernel/cmdline`.
|
||||
|
||||
This is how I setup my kernel arguments (If you're unsure what arguments you
|
||||
need, just check your current systemd-boot configuration, if you followed [the
|
||||
INSTALLATION guide](./01_INSTALLATION.md), you will have it in:
|
||||
`/efi/loader/entries/arch.conf`, all of the `options=` line contain
|
||||
kernel command line args):
|
||||
|
||||
```bash
|
||||
echo "rw loglevel=3" > /etc/kernel/cmdline
|
||||
echo "cryptdevice=LABEL=CRYPTFS:cryptfs:allow-discards" >> /etc/kernel/cmdline
|
||||
echo "root=/dev/mapper/cryptfs rootflags=subvol=/@" >> /etc/kernel/cmdline
|
||||
```
|
||||
|
||||
<!-- markdownlint-disable MD028 -->
|
||||
|
||||
> [!TIP]
|
||||
> If you prefer, you can also create `/etc/kernel/cmdline.d` directory, with
|
||||
> individual files for various parts of the command line. At the end, all of the
|
||||
> options from all files in this directory will be combined.
|
||||
>
|
||||
> You might find this useful if you set a lot of kernel parameters, so you might
|
||||
> have for example: `root.conf`, `apparmor.conf`, ...
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Note that you **shouldn't** be specifying the `cryptdevice` or `root` kernel
|
||||
> parameters if you're using `systemd` initramfs, rather than `BusyBox` one
|
||||
> (which mkinitramfs generates by default).
|
||||
>
|
||||
> That said, you will still need `rootflags` to select the btrfs subvolume
|
||||
> though, unless the root partition is your default subvolume.
|
||||
>
|
||||
> If you aren't sure which initramfs you're using, it's probably `BusyBox`.
|
||||
|
||||
<!-- markdownlint-disable MD028 -->
|
||||
|
||||
## Modify the linux preset for mkinitcpio to build UKIs
|
||||
|
||||
Now open `/etc/mkinitcpio.d/linux.preset`, where you'll want to:
|
||||
|
||||
- Uncomment `ALL_config`
|
||||
- Comment `default_image`
|
||||
- Uncomment `default_uki` (unified kernel image)
|
||||
- Uncomment `default_options`
|
||||
- Comment `fallback_image`
|
||||
- Uncomment `fallback_uki`
|
||||
|
||||
## Recreate /efi
|
||||
|
||||
First, we'll need to unmount `/boot`, which is currently bind-mounted to
|
||||
`/efi/EFI/arch`. This is because we'll no longer be storing the kernel,
|
||||
initramfs, nor the microcode in the EFI partition at all. The EFI partition will
|
||||
now only contain the final UKI, the rest can be left in `/boot`, which will now
|
||||
be a part of the root partition, not mounted anywhere.
|
||||
|
||||
```bash
|
||||
umount /boot
|
||||
vim /etc/fstab # remove the bind mount entry for /boot
|
||||
```
|
||||
|
||||
Now, we will clear the EFI partition and install `systemd-boot` again from
|
||||
scratch:
|
||||
|
||||
```bash
|
||||
rm -rf /efi/*
|
||||
```
|
||||
|
||||
Now, we will create a `/efi/EFI/Linux` directory, which will contain all of our
|
||||
UKIs. (You can change the location in `/etc/mkinitcpio.d/linux.preset` if you
|
||||
wish to use some other directory in the EFI partition, or you want a different
|
||||
name for the UKI file. Note that it is recommended that you stick with the same
|
||||
directory, as most boot loaders will look there when searching for UKIs.)
|
||||
|
||||
```bash
|
||||
mkdir -p /efi/EFI/Linux
|
||||
```
|
||||
|
||||
Finally, we will reinstall the kernel and microcode, re-populating `/boot` (now
|
||||
on the root partition).
|
||||
|
||||
This will also trigger a initramfs rebuild, which will now create the UKI image
|
||||
based on the `linux.preset` file.
|
||||
|
||||
```bash
|
||||
pacman -S linux amd-ucode # or intel-ucode
|
||||
```
|
||||
|
||||
## Proceeding without a boot manager
|
||||
|
||||
Because the Unified Kernel Images can actually be booted into directly from the
|
||||
UEFI, you don't need to have a boot manager installed at all. Instead, you can
|
||||
simply add the UKIs as entries to the UEFI boot menu.
|
||||
|
||||
> [!NOTE]
|
||||
> I prefer to still use a full boot manager alongside UKIs, as they allow you to
|
||||
> have a nice graphical boot menu, from which you can dynamically override the
|
||||
> kernel parameters during boot, or have extra entries for different operating
|
||||
> systems, without having to rely on the specific implementation of the boot
|
||||
> menu in your UEFI firmware (which might take really long to open, or just
|
||||
> generally not provide that good/clean experience).
|
||||
>
|
||||
> Do note though that going without a boot manager is technically a safer
|
||||
> approach, as it cuts out the middle-man entirely, whereas with a boot manager,
|
||||
> your UEFI firmware will be booting the EFI image of your boot manager, only to
|
||||
> then boot your own EFI image, being the UKI.
|
||||
>
|
||||
> Regardless, I still like to use `systemd-boot`, instead of booting UKIs
|
||||
> directly. If you wish to do the same, skip this section.
|
||||
|
||||
<!-- markdownlint-disable MD013 -->
|
||||
|
||||
```bash
|
||||
pacman -S efibootmgr
|
||||
efibootmgr --create --disk /dev/disk/nvme0n1 --part 1 --label "Arch Linux" --loader 'EFI\Linux\arch-linux.efi' --unicode
|
||||
efibootmgr -c -d /dev/disk/nvme0n1 -p 1 -L "Arch Linux Fallback" -l 'EFI\Linux\arch-linux-fallback.efi' -u
|
||||
pacman -R systemd-boot
|
||||
```
|
||||
|
||||
<!-- markdownlint-enable MD013 -->
|
||||
|
||||
You can also specify additional kernel parameters / override the default ones in
|
||||
the UKI, by simply adding a string as a last positional argument to the
|
||||
`efibootmgr` command, allowing you to create entires with different kernel
|
||||
command lines easily.
|
||||
|
||||
## Proceeding with a boot manager
|
||||
|
||||
> [!NOTE]
|
||||
> This is an alternative to the above, see the note in the previous section to
|
||||
> understand the benefits/cons of either approach.
|
||||
|
||||
Most boot managers can handle loading your UKIs. The boot manager of my choice
|
||||
is `systemd-boot`, but if you wish, you should be able to use grub, or any other
|
||||
boot manager too. That said, this guide will only mention `systemd-boot`.
|
||||
|
||||
All that we'll need to do now is installing systemd-boot, just like during the
|
||||
initial OS installation:
|
||||
|
||||
````bash
|
||||
```bash
|
||||
bootctl install --esp-path=/efi
|
||||
````
|
||||
|
||||
We can now reboot. Systemd-boot will pick up any UKI images in `/efi/EFI/Linux`
|
||||
automatically (this path is hard-coded), even without any entry configurations.
|
||||
|
||||
That said, if you do wish to do so, you can still add an explicit entry for your
|
||||
configuration in `/efi/loader/entries/arch.conf`, like so:
|
||||
|
||||
```text
|
||||
title Arch Linux
|
||||
sort-key 0
|
||||
efi /EFI/Linux/arch-linux.efi
|
||||
# If you wish, you can also specify kernel options here, it will
|
||||
# append/override those in the UKI image
|
||||
#options rootflags=subvol=/@
|
||||
#options rw loglevel=3
|
||||
```
|
||||
|
||||
Although do note that if your UKI image is stored in `/efi/EFI/Linux`, because
|
||||
systemd-boot picks it up automatically, you will see the entry twice, so you'll
|
||||
likely want to change the target directory for the UKIs (in
|
||||
`/etc/mkinitcpio.d/linux.preset`) to something else.
|
||||
|
||||
I however wouldn't recommend this approach, and I instead just let systemd-boot
|
||||
autodetect the images, unless you need something specific.
|
||||
|
||||
If everything went well, you should see a new systemd based initramfs, from
|
||||
where you'll be prompted for the LUKS2 password.
|
186
guides/04_SECURE_BOOT.md
Normal file
186
guides/04_SECURE_BOOT.md
Normal file
|
@ -0,0 +1,186 @@
|
|||
# Secure Boot
|
||||
|
||||
This guide will show you how to set up UEFI Secure Boot with Arch Linux. Once
|
||||
finished, you will be left with a system that doesn't allow booting any
|
||||
untrusted EFI images (other operating systems, fraudulently modified kernels,
|
||||
...) on your machine.
|
||||
|
||||
This guide assumes you're following from the
|
||||
[INSTALLATION](./01_INSTALLATION.md) guide and that you're using [UNIFIED KERNEL
|
||||
IMAGES](./03_UNIFIED_KERNEL_IMAGES.md) (UKIs) for booting.
|
||||
|
||||
## Security requirements
|
||||
|
||||
Meeting these requirements is optional, as it is possible to set up secure boot
|
||||
without them. That said, if you don't meet these, setting up secure boot will
|
||||
not be a very effective security measure and it might be more of a time waste
|
||||
than a helpful means of enhancing your security.
|
||||
|
||||
First requirement is to set up a **BIOS Password**. This is a password that you
|
||||
will be asked for every time you wish to enter the BIOS (UEFI). This is
|
||||
necessary, as without it, an attacker could very easily just go to the BIOS and
|
||||
disable Secure Boot.
|
||||
|
||||
The second requirement is having **disk encryption**, at least for the root
|
||||
partition. This is important, because the UEFI signing keys will be stored here,
|
||||
and you don't want someone to potentially be able to get access to them, as it
|
||||
would allow them to sign any malicious images, making them pass secure boot.
|
||||
|
||||
> [!WARNING]
|
||||
> Even after following all of these, you should be aware that Secure Boot isn't
|
||||
> an unbreakable solution. In fact, if someone is able to get a hold of your
|
||||
> machine, they can simply pull out the CMOS battery, which usually resets the
|
||||
> UEFI. That means turning off Secure Boot, and getting rid of the BIOS
|
||||
> password.
|
||||
>
|
||||
> While Secure Boot is generally a good extra measure to have, it is by no means
|
||||
> a reliable way to completely prevent others from ever being able to boot
|
||||
> untrusted systems, unless you use a specialized motherboard, which persists
|
||||
> the UEFI state.
|
||||
|
||||
## Enter Setup mode
|
||||
|
||||
To allow us to upload new signing keys into secure boot, we will need to enter
|
||||
"setup mode". This should be possible by going to the Secure Boot category in
|
||||
your UEFI settings, and clicking on Delete/Clear certificates, or there could
|
||||
even just be a "Setup Mode" option directly.
|
||||
|
||||
Once enabled, save the changes and boot back into Arch linux.
|
||||
|
||||
```bash
|
||||
pacman -S sbctl
|
||||
sbctl status
|
||||
```
|
||||
|
||||
Make sure that `sbctl` reports that Setup Mode is Enabled.
|
||||
|
||||
## Create Secure Boot keys
|
||||
|
||||
We can now create our new signing keys for secure boot. These keys will be
|
||||
stored in `/usr/share/secureboot` (so in our encrypted root partition). Once
|
||||
created, we will add (enroll) these keys into the UEFI firmware (only possible
|
||||
when in setup mode)
|
||||
|
||||
```bash
|
||||
sbctl create-keys
|
||||
sbctl enroll-keys -m
|
||||
```
|
||||
|
||||
<!-- markdownlint-disable MD028 -->
|
||||
|
||||
> [!WARNING]
|
||||
> The `-m` option (also known as `--microsoft`) will make sure to also include
|
||||
> the Microsoft signing keys. This is required by most motherboards, not using
|
||||
> it could brick your device.
|
||||
|
||||
> [!NOTE]
|
||||
> If you encounter "File is immutable" warnings after running sbctl, it should
|
||||
> be safe to simply add the `-i` (or `--ignore-immutable`) flag, which will run
|
||||
> `chattr` and remove the immutable flags from these files for you.
|
||||
>
|
||||
> You can also do so manually with `chattr -i [file]` for all the listed
|
||||
> immutable files and then re-run the enroll-keys command.
|
||||
>
|
||||
> This happens because the Linux kernel will sometimes mark the runtime EFI
|
||||
> files as immutable for security - to prevent bricking the device with just `rm
|
||||
-rf /*`, or similar stupid commands, however since we trust that `sbctl` will
|
||||
> work and won't do anything malicious, we can just remove the immutable flag,
|
||||
> and re-running will now work).
|
||||
>
|
||||
> If you still encounter errors even with this flag, it means you have probably
|
||||
> done something wrong when entering the setup mode. Try looking for a option
|
||||
> like "Reset keys" in your UEFI, then try this again.
|
||||
|
||||
<!-- markdownlint-enable MD028 -->
|
||||
|
||||
## Sign the bootloader and Unified Kernel Images
|
||||
|
||||
Finally then, we can sign the `.efi` executables that we'd like to use:
|
||||
|
||||
```bash
|
||||
sbctl sign -s -o /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed /usr/lib/systemd/boot/efi/systemd-bootx64.efi
|
||||
sbctl sign -s /efi/EFI/BOOT/BOOTX64.EFI
|
||||
sbctl sign -s /efi/EFI/systemd/systemd-bootx64.efi
|
||||
sbctl sign -s /efi/EFI/Linux/arch-linux.efi
|
||||
sbctl sign -s /efi/EFI/Linux/arch-linux-fallback.efi
|
||||
```
|
||||
|
||||
(If you're booting directly from UKI images, only sign those - in `/efi/EFI/Linux`)
|
||||
|
||||
The `-s` flag means save: The files will be automatically re-signed when we
|
||||
update the kernel (via a sbctl pacman hook).
|
||||
|
||||
> [!TIP]
|
||||
> To make sure that this is the case, we can run `pacman -S linux` and check
|
||||
> that messages about image signing appear.
|
||||
>
|
||||
> They should look something like this:
|
||||
>
|
||||
> ```text
|
||||
> Signing /efi/EFI/Linux/arch-linux.efi
|
||||
> ✓ Signed /efi/EFI/Linux/arch-linux.efi
|
||||
> ...
|
||||
> Signing /efi/EFI/Linux/arch-linux-fallback.efi
|
||||
> ✓ Signed /efi/EFI/Linux/arch-linux-fallback.efi
|
||||
> ...
|
||||
> File has already been signed /efi/EFI/Linux/arch-linux-fallback.efi
|
||||
> File has already been signed /efi/EFI/Linux/arch-linux.efi
|
||||
> File has already been signed /efi/EFI/systemd/systemd-bootx64.efi
|
||||
> File has already been signed /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed
|
||||
> File has already been signed /efi/EFI/BOOT/BOOTX64.EFI
|
||||
> ```
|
||||
|
||||
When done, we can make sure that everything that needed to be signed really was
|
||||
signed with:
|
||||
|
||||
```bash
|
||||
sbctl verify
|
||||
```
|
||||
|
||||
You can also check that setup mode got disabled after enrolling the keys:
|
||||
|
||||
```bash
|
||||
sbctl status
|
||||
```
|
||||
|
||||
Setup mode status should now report as `Disabled`. (Secure boot will still not
|
||||
appear as enabled though.)
|
||||
|
||||
## Reboot with secure boot
|
||||
|
||||
We should now be ready to enable secure boot, as our `.efi` images were signed,
|
||||
and the signing key was enrolled to UEFI firmware. So, all that remains is:
|
||||
|
||||
```bash
|
||||
reboot
|
||||
```
|
||||
|
||||
Boot into UEFI, go to the Secure Boot settings and enable it. (It might get
|
||||
enabled automatically on some UEFI firmware after setup mode, but it's not
|
||||
always the case.)
|
||||
|
||||
### Verify it worked
|
||||
|
||||
To make sure that it worked as expected, and you're booted with secure-boot
|
||||
enabled, you can now run:
|
||||
|
||||
```bash
|
||||
sbctl status
|
||||
```
|
||||
|
||||
It should report `Secure Boot: enabled` or `Secure Boot: enabled (user)`.
|
||||
|
||||
## Why bother?
|
||||
|
||||
As I mentioned, secure boot can be bypassed if someone tries hard enough
|
||||
(pulling the CMOS battery). That then brings to question whether it's even worth
|
||||
it to set it up, when it doesn't really give you that much.
|
||||
|
||||
On its own, I probably wouldn't bother with setting up secure-boot, however
|
||||
secure boot allows me to set up TPM (Trusted Platform Module) to automatically
|
||||
release the decryption keys for my LUKS encrypted root partition, in a secure
|
||||
way. This means I won't have to type my disk password every time I boot which is
|
||||
actually the primary reason why I like having secure-boot enabled.
|
||||
|
||||
For more information on this, check out the follow-up guide:
|
||||
[TPM_UNLOCKING](./06_TPM_UNLOCKING.md).
|
211
guides/05_SYSTEMD_INITRAMFS.md
Normal file
211
guides/05_SYSTEMD_INITRAMFS.md
Normal file
|
@ -0,0 +1,211 @@
|
|||
# Systemd initramfs
|
||||
|
||||
The initial ramdisk is in essence a very small environment (early userspace)
|
||||
whihc loads various kernel modules and sets up necessary things before handing
|
||||
control over to `init` program (systemd).
|
||||
|
||||
By default, Arch Linux uses a BusyBox+udev based initial ramdisk, generated by
|
||||
`mkinitcpio`. This default initrd is essentially just a small script, that
|
||||
executes other scripts, called hooks.
|
||||
|
||||
As an alternative to this, it's possible to have systemd run from the very
|
||||
start, during that initial ramdisk phase. With this approach, the tasks ran at
|
||||
this phase are determined by regular systemd unit files.
|
||||
|
||||
## Why?
|
||||
|
||||
Obviously, BusyBox initramfs works just fine, so why would you want to switch?
|
||||
Well, there's a few reasons:
|
||||
|
||||
- **Consistency across boot phases:** The same systemd process that handles your
|
||||
system after boot can also manage the early userspace during boot, providing
|
||||
consistency in handling services, devices and dependencies throughout the
|
||||
entire boot process.
|
||||
- **Simplified troubleshooting:** The tools and logs available during the boot
|
||||
process will be the same as those used once the system is fully booted,
|
||||
allowing you to troubleshoot problems with familiar tools (`journalctl`,
|
||||
`systemctl`, ...)
|
||||
- **Consistent Unit Files:** Since systemd uses the same unit files in the
|
||||
initramfs as it does in the fully booted system, the configuration for many
|
||||
tasks (like mounting filesystems) is unified, reducing duplication of
|
||||
configuration files.
|
||||
- **TPM Unlocking Support:** Systemd has built-in support for requesting data
|
||||
from TPM, allowing for a setup with TPM auto-unlocking an encrypted root
|
||||
partition, without having to specify the decryption password.
|
||||
- **Parallel Service Startup:** Systemd is known for the ability to start
|
||||
services in parallel, which can potentially **speed up the boot process**
|
||||
compared to sequential script-based approach.
|
||||
- **Integrated Mount Handling:** With systemd, managing complex mount setup
|
||||
(e.g. LVM RAID) can be more seamless, since it natively supports these and can
|
||||
handle them with less custom scripting.
|
||||
|
||||
That said, it's important to also mention some downsides and reasons why you
|
||||
might not want to use systemd-based initramfs:
|
||||
|
||||
- **Simplicity:** If you prefer a simple, more minimalistic approach,
|
||||
BusyBox-based initramfs might be sufficient and easier to manage.
|
||||
- **Size:** A systemd-based initramfs might be larger than a minimal
|
||||
BusyBox-based initramfs, which could be a concern on systems with very limited
|
||||
space.
|
||||
- **Compatibility:** If you're running some custom scripts or hooks, they might
|
||||
not work with a systemd-based initramfs.
|
||||
|
||||
## Switching to systemd initramfs
|
||||
|
||||
Open `/etc/mkinitcpio.conf` and find a line that starts with `HOOKS=`
|
||||
|
||||
- Change `udev` to `systemd`
|
||||
- Change `keymap consolefont` to `sd-vconsole`
|
||||
- Add `sd-encrypt` before `block`, and remove `encrypt`
|
||||
- If you were using `mkinitcpio-numlock`, also remove `numlock`, it doesn't work
|
||||
with systemd (we'll go over how to auto-enable numlock later)
|
||||
|
||||
Additionally, with systemd initramfs, you shouldn't be specifying `root` nor
|
||||
`cryptdevice` kernel arguments, as systemd can actually pick those up
|
||||
automatically (they'll be discovered by [systemd-cryptsetup-generator] and
|
||||
auto-mounted from initramfs via [systemd-gpt-auto-generator]). We will however
|
||||
still need the `rootflags` argument for selecting the btrfs subvolume (unless
|
||||
your default subvolume is the root partition subvolume).
|
||||
|
||||
[systemd-cryptsetup-generator]: https://wiki.archlinux.org/title/Dm-crypt/System_configuration#Using_systemd-cryptsetup-generator
|
||||
[systemd-gpt-auto-generator]: https://wiki.archlinux.org/title/Systemd#GPT_partition_automounting
|
||||
|
||||
So, let's edit our kernel parameters:
|
||||
|
||||
```bash
|
||||
echo "rw loglevel=3" > /etc/kernel/cmdline # overwrite the existing cmdline
|
||||
echo "rootflags=subvol=/@" >> /etc/kernel/cmdline
|
||||
```
|
||||
|
||||
You'll also need to modify the `/etc/fstab`, as systemd will not use the
|
||||
`/dev/mapper/cryptfs` name, but rather you'll have a `/dev/gpt-auto-root`
|
||||
(there'll also be `/dev/gpt-auto-root-luks`, which is the encrypted partition).
|
||||
If you prefer using a mapper device, you can also use `/dev/mapper/root`.
|
||||
Alternatively, you can use the label to mount. (if you followed the
|
||||
installation guide, that would be `/dev/disk/by-label/FS`.)
|
||||
|
||||
```bash
|
||||
vim /etc/fstab
|
||||
```
|
||||
|
||||
Finally, regenerate the initramfs with: `pacman -S linux` (you could also do
|
||||
`mkinitcpio -P`, however that won't trigger the pacman hook which auto-signs our
|
||||
UKI images for secure boot, so you'd have to re-sign them with `sbctl` manually,
|
||||
if you're using secure-boot) and reboot to check if it worked.
|
||||
|
||||
## Activating numlock
|
||||
|
||||
Since we had to remove `mkinitcpio-numlock`, as that hook isintended for BusyBox
|
||||
based initrd, we'll want to have an alternative available.
|
||||
|
||||
First though, we should also remove the package: `pacman -R mkinitcpio-numlock`.
|
||||
|
||||
### The simple, but imperfect option
|
||||
|
||||
There is a `systemd-numlockontty` AUR package which creates a systemd service
|
||||
that enables numlock in TTYs after booting (you'll need to enable it), this
|
||||
however doesn't happen in initramfs directly, only afterwards.
|
||||
|
||||
Depending on what you will need, this may be sufficient. If you are going to be
|
||||
typing a decryption password at this early stage and you wish to have numlock
|
||||
support there, you will need to do some more work.
|
||||
|
||||
### The proper solution
|
||||
|
||||
To enable numlock before you're prompted for the decryption password, we'll need
|
||||
to create a custom initcpio hook, that will return a systemd service which will
|
||||
do the enabling. We'll put this hook into `/usr/lib/initcpio/install/numlock`,
|
||||
with the following content:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
build() {
|
||||
add_binary /bin/bash
|
||||
add_binary /usr/bin/setleds
|
||||
add_binary /usr/local/bin/numlock
|
||||
|
||||
cat >"$BUILDROOT/usr/lib/systemd/system/numlock.service" <<EOF
|
||||
[Unit]
|
||||
Description=Enable numlock
|
||||
Before=cryptsetup-pre.target
|
||||
DefaultDependencies=no
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=/usr/local/bin/numlock
|
||||
EOF
|
||||
|
||||
add_systemd_unit cryptsetup-pre.target
|
||||
cd "$BUILDROOT/usr/lib/systemd/system/sysinit.target.wants" || exit
|
||||
ln -sf /usr/lib/systemd/system/cryptsetup-pre.target cryptsetup-pre.target
|
||||
ln -sf /usr/lib/systemd/system/numlock.service numlock.service
|
||||
}
|
||||
|
||||
help() {
|
||||
cat <<EOF
|
||||
This hook adds support to enable numlock before sd-encrypt hook is run.
|
||||
EOF
|
||||
}
|
||||
```
|
||||
|
||||
This script is also present in my dotfiles, so you can just copy it from there:
|
||||
|
||||
```bash
|
||||
cp ~/dots/root/usr/lib/initcpio/install/numlock /usr/lib/initcpio/install
|
||||
```
|
||||
|
||||
Next we will need to create that `/usr/local/bin/numlock` script. This script
|
||||
will do the actual enabling of numlock. Note that we can only use the binaries
|
||||
that we explicitly included in our hook inside our script.
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
for tty in /dev/tty[0-9]; do
|
||||
/usr/bin/setleds -D +num < "$tty"
|
||||
done
|
||||
```
|
||||
|
||||
If you ran the `install_root.sh` script from my dotfiles during
|
||||
[INSTALLATION](./01_INSTALLATION.md), this script will already be present in
|
||||
your `/usr/local/bin`
|
||||
|
||||
Now we will need to add our custom new `numlock` hook to
|
||||
`/etc/mkinitcpio.conf`, before the `sd-encrypt` hook (assuming you're using
|
||||
encryption), but after the `keyboard` and `sd-vconsole` hooks.
|
||||
|
||||
Finally, we'll need to rebuild initramfs, which we should trigger with `sudo
|
||||
pacman -S linux`, to make sure the secure-boot signing also runs. When
|
||||
re-building the initramfs, pay attention on the output, you should see it pass
|
||||
with no errors:
|
||||
|
||||
```text
|
||||
-> Running build hook: [base]
|
||||
-> Running build hook: [systemd]
|
||||
-> Running build hook: [autodetect]
|
||||
-> Running build hook: [microcode]
|
||||
-> Running build hook: [modconf]
|
||||
-> Running build hook: [kms]
|
||||
-> Running build hook: [keyboard]
|
||||
-> Running build hook: [sd-vconsole]
|
||||
-> Running build hook: [numlock] # <-- make sure this is present
|
||||
-> Running build hook: [sd-encrypt]
|
||||
-> Running build hook: [block]
|
||||
-> Running build hook: [filesystems]
|
||||
-> Running build hook: [fsck]
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> If you see some warnings there, like:
|
||||
> `==> WARNING: Possibly missing firmware for module: 'xyz'`, you can usually
|
||||
> safely ignore these. Just make sure there's no `==> ERROR: ...`
|
||||
|
||||
If you didn't see any errors, you can now reboot.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> In some cases, the numlock led indicator might not turn on immediately, even
|
||||
> though numlock was actually turned on. This may mislead you towards thinking
|
||||
> it is not on, even though it actually is. I'd recommend trying it out by
|
||||
> actually typing something it at this time.
|
||||
>
|
||||
> Note that after this early boot stage, the indicator should light up
|
||||
> eventually.
|
227
guides/06_TPM_UNLOCKING.md
Normal file
227
guides/06_TPM_UNLOCKING.md
Normal file
|
@ -0,0 +1,227 @@
|
|||
# TPM Unlocking
|
||||
|
||||
This will explain how to set up TPM (Trusted Platform Module) based automatic
|
||||
unlocking of your LUKS encrypted partition(s). Encryption usually requires that
|
||||
you manually type the password in each time you boot. This can however be pretty
|
||||
annoying (especially if you use a long password, like I do). This guide aims to
|
||||
fix this problem, without compromising security.
|
||||
|
||||
Once finished, this will basically store another decryption key(s) to your
|
||||
encrypted partition(s) in the TPM module. During boot, while in initrd, we will
|
||||
request this decryption key from TPM, which will only release it under certain
|
||||
conditions, to ensure safety.
|
||||
|
||||
The guide assumes you have already a working Arch Linux system, that uses LUKS
|
||||
encryption, having followed the [INSTALLATION guide](./01_INSTALLATION.md). You
|
||||
will also need to set up secure-boot, as described in
|
||||
[SECURE_BOOT](./04_SECURE_BOOT.md). This is a requirement, as while it is
|
||||
possible to set up TPM unlocking without it, doing so is incredibly insecure,
|
||||
and might lead to unauthorized users getting TPM to release your decryption
|
||||
keys. Additionally, you will need to be using a [SYSTEMD BASED
|
||||
INITRAMFS](./05_SYSTEMD_INITRAMFS.md), as the default BusyBox one doesn't
|
||||
support TPM unlocking.
|
||||
|
||||
> [!WARNING]
|
||||
> This solution will be mostly safe, however, it is technically possible to hook
|
||||
> up wires to the motherboard, to listen to the communication coming from the
|
||||
> TPM chip. In that case, the attacker would be able to observe the key as it
|
||||
> gets released by the chip. They could then take out your SSD/HDD, and mount it
|
||||
> on their machine, using these obtained keys to decrypt the contents. See:
|
||||
> <https://astralvx.com/stealing-the-bitlocker-key-from-a-tpm/>
|
||||
>
|
||||
> If you can't afford to be vulnerable to this type of attack, you can still
|
||||
> follow through with this, however instead of the TPM seamlessly releasing the
|
||||
> decryption password, you can require a password to be entered, without which
|
||||
> TPM won't release the decryption password.
|
||||
>
|
||||
> This can be useful if you use a very long encryption passwords, and you want
|
||||
> to be able to enter a shorter passphrase instead (TPM has brute-force
|
||||
> protection, so a short password isn't actually that unsafe to use).
|
||||
|
||||
## Check if you actually have the TPM module
|
||||
|
||||
First, you will want to verify that your machine even has the TPM v2 module. To
|
||||
do so, you can use the following command:
|
||||
|
||||
```bash
|
||||
bootctl status
|
||||
```
|
||||
|
||||
You should see `TPM2 Support: yes` in the output.
|
||||
|
||||
## Choosing PCRs
|
||||
|
||||
PCR stands for Platform Configuration Register, and all TPM v2 modules have a
|
||||
bunch of these registers, which hold hashes about the system's state. These
|
||||
registers are read-only, and their value is set by the TPM module itself.
|
||||
|
||||
The data held by the TPM module (our LUKS encryption key) can then only be
|
||||
accessed when all of the selected PCR registers contain the expected values. You
|
||||
can find a list of the PCR registers on [Arch
|
||||
Wiki](https://wiki.archlinux.org/title/Trusted_Platform_Module#Accessing_PCR_registers).
|
||||
|
||||
You can look at the current values of these registers with this command:
|
||||
|
||||
```bash
|
||||
systemd-analyze pcrs
|
||||
```
|
||||
|
||||
For our purposes, we will choose these:
|
||||
|
||||
- **PCR0:** Hash of the UEFI firmware executable code (may change if you update
|
||||
UEFI)
|
||||
- **PCR7:** Secure boot state - contains the certificates used to validate each
|
||||
boot application
|
||||
- **PCR12:** Overridden kernel command line, credentials
|
||||
|
||||
> [!IMPORTANT]
|
||||
> If you're using a boot loader (rather than booting directly from the Unified
|
||||
> Kernel Images - EFI files), it is crucial that we choose all 3, including
|
||||
> PCR12, as many tutorials only recommend 0 and 7, which would however lead to a
|
||||
> security hole, where an attacker would be able to remove the drive with the
|
||||
> (unencrypted) EFI partition, and modify the boot loader config. (With
|
||||
> systemd-boot, this would be `loaders/loader.conf`).
|
||||
>
|
||||
> From there, the attacker could simply add a kernel argument like
|
||||
> `init=/bin/bash`, or just enable editor support, allowing them to edit the
|
||||
> parameters from the boot menu on the fly (The editor is actually enabled by
|
||||
> default for systemd-boot). This would then bypass systemd as the init system
|
||||
> and instead make the kernel run bash executable as the PID=1 (init) program.
|
||||
> This would mean you would get directly into bash console that is running as
|
||||
> root, without any need to enter a password.
|
||||
>
|
||||
> From that bash console, they could get the TPM to release the decryption
|
||||
> password manually, as all of the selected PCRs do match.
|
||||
>
|
||||
> This wouldn't violate secure boot, as the `.efi` image files were unchanged,
|
||||
> and are still signed, so the attacker would be able to boot into the system
|
||||
> without issues.
|
||||
>
|
||||
> However, with PCR12, this is prevented, as it detects that the kernel cmdline
|
||||
> arguments which were used, and if they don't match the recorded parameters
|
||||
> during enrollment, TPM will not release the key.
|
||||
>
|
||||
> The nice thing about also selecting PCR12 is that it will actually allow us to
|
||||
> securely keep systemd-boot editor support, which can be very useful for
|
||||
> debugging, as all that will happen if we do edit the kernel command line will
|
||||
> be that the TPM module will not release the credentials, and the initrd will
|
||||
> just ask us to enter the password manually.
|
||||
|
||||
Optionally, you may also consider these:
|
||||
|
||||
- **PCR1:** Hash of the UEFI firmware data (changes when you change your BIOS settings)
|
||||
- **PCR4:** Boot manager (changes when you change the boot manager)
|
||||
|
||||
> [!NOTE]
|
||||
> You may be tempted to also add **PCR11**, which is a hash of the Unified
|
||||
> Kernel Image, so that no other UKI can be booted, but this isn't necessary,
|
||||
> as we're signing our UKIs, which means untrusted ones wouldn't pass secure
|
||||
> boot, and if secure boot got disabled, PCR7 wouldn't pass.
|
||||
>
|
||||
> Additionally, enabling PCR11 would mean that you'd need to update the TPM
|
||||
> every time your kernel/microcode/initrd/... is updated, as these will change
|
||||
> the UKI file.
|
||||
|
||||
## Enroll a new key into TPM
|
||||
|
||||
The following command will enroll a new randomly generated key into the TPM
|
||||
module and add it as a new keyslot of the specified LUKS2 encrypted device.
|
||||
|
||||
We also specify `--tpm2-pcrs=0+7+12`, which selects the PCR registers that we
|
||||
decided on above.
|
||||
|
||||
```bash
|
||||
sudo systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7+12 /dev/gpt-auto-root-luks
|
||||
```
|
||||
|
||||
<!-- markdownlint-disable MD028 -->
|
||||
|
||||
> [!NOTE]
|
||||
> If you already have something in the tpm2 module, you'll want to add
|
||||
> `--wipe-slot=tpm2` too.
|
||||
>
|
||||
> Note that wiping the slot will also remove the LUKS key slot that was added
|
||||
> in the partition.
|
||||
|
||||
> [!TIP]
|
||||
> If you're extra paranoid, you can also provide `--tpm2-with-pin=yes`, to
|
||||
> prompt for a PIN code (passphrase) on each boot.
|
||||
>
|
||||
> I have mentioned why you may want to do this in the beginning.
|
||||
>
|
||||
> In case you do want to go with a PIN, you can also safely drop PCR12, as you
|
||||
> will be asked for credentials each time anyways, and at that point, the TPM
|
||||
> unlocking is basically just as secure as regular passphrase unlocking, which
|
||||
> systemd would fall back to if PCR12 wasn't met.
|
||||
|
||||
<!-- markdownlint-enable MD028 -->
|
||||
|
||||
You will now be prompted for an existing LUKS password (needed to add a new LUKS
|
||||
keyslot).
|
||||
|
||||
## Reboot
|
||||
|
||||
All that remains now is rebooting. The system should now get unlocked
|
||||
automatically, without prompting for the password / prompting for the TPM PIN
|
||||
instead of a decryption password.
|
||||
|
||||
If you're using a bootloader, I'd recommend also trying to modify the kernel
|
||||
parameters, to make sure that TPM does not release the key anymore, and you will
|
||||
be prompted to enter it manually.
|
||||
|
||||
## Moving to a recovery key
|
||||
|
||||
Once you have confirmed that TPM unlocking is working, you can now optionally
|
||||
get rid of your original LUKS key, in favor of a randomly generated recovery
|
||||
key.
|
||||
|
||||
You might want to do this as this recovery key will be guaranteed to have high
|
||||
entropy, likely making it a lot more secure than your original key, further
|
||||
improving your chances, if someone attempts a brute-force decryption of your
|
||||
drive.
|
||||
|
||||
To generate a recovery key, you can actually also just use `systemd-cryptenroll`
|
||||
(though you can also do it manually with `cryptsetup`):
|
||||
|
||||
```bash
|
||||
systemd-cryptenroll /dev/gpt-auto-root-luks --recovery-key
|
||||
```
|
||||
|
||||
This will give you a randomized key, using characters that are easy to type. You
|
||||
will even be given a QR code that can be scanned directly to save the password
|
||||
on your phone.
|
||||
|
||||
Before proceeding with removing your own key, let's first make absolutely
|
||||
certain that the recovery key you saved does in fact work. Without doing this,
|
||||
you may get locked out!
|
||||
|
||||
```bash
|
||||
cryptsetup luksOpen /dev/gpt-auto-root-luks crypttemp # enter the recovery key
|
||||
cryptsetup luksClose crypttemp
|
||||
```
|
||||
|
||||
If this worked, proceed to:
|
||||
|
||||
```bash
|
||||
cryptsetup luksRemoveKey /dev/gpt-auto-root-luks # Enter the original key to be deleted
|
||||
```
|
||||
|
||||
## Removing the key from TPM
|
||||
|
||||
In case you'd ever want to remove the LUKS key from TPM, you can do so simply
|
||||
with:
|
||||
|
||||
```bash
|
||||
csystemd-cryptenroll --wipe-slot=tpm2
|
||||
```
|
||||
|
||||
This will actually also remove the LUKS key from the `/dev/gpt-auto-root-luks`
|
||||
device as well as wiping it from the TPM2 chip.
|
||||
|
||||
## Sources / Attribution
|
||||
|
||||
- <https://nixos.wiki/wiki/TPM>
|
||||
- <https://discourse.nixos.org/t/full-disk-encryption-tpm2/29454/6>
|
||||
- <https://wiki.archlinux.org/title/systemd-cryptenroll>
|
||||
- <https://wiki.archlinux.org/title/Trusted_Platform_Module#Accessing_PCR_registers>
|
||||
- <https://pawitp.medium.com/full-disk-encryption-on-arch-linux-backed-by-tpm-2-0-c0892cab9704>
|
280
guides/99_BATTERY_OPTIMIZATIONS.md
Normal file
280
guides/99_BATTERY_OPTIMIZATIONS.md
Normal file
|
@ -0,0 +1,280 @@
|
|||
# Battery Optimizations
|
||||
|
||||
This guide goes over the various optimizations for laptops that you can
|
||||
configure to improve your battery life.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> You will need to follow this guide even if you're using my dotfiles, as it
|
||||
> requires enabling certain services which I don't enable automatically from
|
||||
> the installation scripts.
|
||||
>
|
||||
> This is because not all devices need power management services running
|
||||
> (desktop devices don't have a battery).
|
||||
|
||||
## UPower
|
||||
|
||||
UPower is a DBus service that provides power management support to
|
||||
applications, which can request data about the current power state through this
|
||||
DBus interface.
|
||||
|
||||
Additionally, UPower can perform a certain action when your battery life
|
||||
reaches a critical point, like entering hibarnation when below 2%.
|
||||
|
||||
```bash
|
||||
pacman -S upower
|
||||
systemctl start --now upower
|
||||
```
|
||||
|
||||
You can adjust UPower configuration in `/etc/UPower/UPower.conf`, I quite like
|
||||
the defaults settings here. The relevant settings to look at are:
|
||||
|
||||
```conf
|
||||
PercentageLow=20.0
|
||||
PercentageCritical=5.0
|
||||
PercentageAction=2.0
|
||||
CriticalPowerAction=HybridSleep
|
||||
```
|
||||
|
||||
## Acpid
|
||||
|
||||
Acpid is a daemon that can deliver ACPI power management events. When an event
|
||||
occurs, it executes a program to handle that event. These events are:
|
||||
|
||||
- Pressing special keys, including the Power/Sleep/Suspend button, but also
|
||||
things like wlan/airplane mode toggle button, volume buttons, brightness, ...
|
||||
- Closing a notebook lid
|
||||
- (Un)Plugging an AC power adapter from a notebook
|
||||
- (Un)Plugging phone jack etc.
|
||||
|
||||
By default, these events would otherwise go unhandled, which isn't ideal.
|
||||
|
||||
```bash
|
||||
pacman -S acpid
|
||||
systemctl enable --now acpid
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> By default `acpid` already has some basic handling of these ACPI events, so
|
||||
> you shouldn't need to change anything, however, if you would want to run
|
||||
> something custom on one of these events, you can configure it to do so in
|
||||
> `/etc/acpi/handler.sh`
|
||||
|
||||
## Systemd suspend-then-hibernate
|
||||
|
||||
I like to use `systemctl suspend-then-hibernate` command when entering a
|
||||
suspend state (usually configured from an idle daemon, such as hypridle or
|
||||
swayidle). This command allows my system to remain suspended for some amount of
|
||||
time, after which it will enter hibernation. This is really nice, because if I
|
||||
forget that I had my laptop suspended and leave it like that while unplugged
|
||||
for a long amount of time, this will prevent the battery from being drained for
|
||||
no reason.
|
||||
|
||||
To configure automatic hibernation with this command, we'll want to modify
|
||||
`/etc/systemd/sleep.conf`, and add:
|
||||
|
||||
```conf
|
||||
HibernateDelaySec=10800
|
||||
```
|
||||
|
||||
That will configure automatic hibernation after 3 hours of being in a suspend
|
||||
state.
|
||||
|
||||
## Power Profiles Daemon
|
||||
|
||||
Many people like using something complex like TLP to manage power, however, in
|
||||
many cases, you can achieve good results with something much simpler:
|
||||
`power-profiles-daemon`.
|
||||
|
||||
Simply put, `power-profiles-daemon` is a CPU throttle, allowing you to switch
|
||||
between various "power profiles" (power-saver, balanced, performance). I like
|
||||
using a custom shell-script that checks the current battery percentage and
|
||||
status (charging/discharging) and dynamically set the power profile based on
|
||||
these values.
|
||||
|
||||
<!-- markdownlint-disable MD028 -->
|
||||
|
||||
> [!NOTE]
|
||||
> Power Profiles Daemon only performs a subset of what TLP would do. Which of
|
||||
> these tools you wish to use depends on your workfload and preferences:
|
||||
>
|
||||
> - If the laptop frequently runs under medium or high load, such as during
|
||||
> video playback or compiling, using `power-saver` profile with
|
||||
> `power-profiles-daemon` can provide similar energy savings as TLP.
|
||||
> - However, TLP offers advantages over `power-profiles-daemon` when the laptop
|
||||
> is idle, such as during periods of no user input or low load operations
|
||||
> like text editing or browsing.
|
||||
>
|
||||
> In my personal opinion, `power-profiles-daemon` is quite sufficient and I
|
||||
> don't have a great need for TLP. Also TLP is actually quite limiting in it's
|
||||
> configuration in comparison to being able to use something like a shell script
|
||||
> and switch profiles depending on both the charging state & the current
|
||||
> percentage or any other custom rules whereas TLP only exposes some simple
|
||||
> configuration options, that will enable performance/balanced mode when on AC
|
||||
> power and power-safe when on battery power, but you can't really mess with
|
||||
> anything more dynamic.
|
||||
|
||||
> [!TIP]
|
||||
> If you think you'd prefer TLP over `power-profiles-daemon`, feel free to skip
|
||||
> this section, the section below will cover TLP as an alternative to this.
|
||||
|
||||
> [!TIP]
|
||||
> It may be worth it to look into
|
||||
> [`system76-power`](https://github.com/pop-os/system76-power) as an
|
||||
> alternative to `power-profiles-daemon`.
|
||||
|
||||
<!-- markdownlint-enable MD028 -->
|
||||
|
||||
To set up power-profiles-daemon, we'll first install it and enable it as a
|
||||
systemd service:
|
||||
|
||||
```bash
|
||||
pacman -S power-profiles-daemon
|
||||
systemctl enable --now power-profiles-daemon
|
||||
```
|
||||
|
||||
### Setting power profile manually
|
||||
|
||||
To try things out, you can set the power profile manually, using
|
||||
`powerprofilesctl` command:
|
||||
|
||||
```bash
|
||||
powerprofilesctl set power-saver
|
||||
powerprofilesctl set balanced
|
||||
powerprofilesctl set performance # won't work on all machines
|
||||
```
|
||||
|
||||
However, having to set your power profile manually each time wouldn't be very
|
||||
convenient, so I'm only showing this as an example / something you can try out
|
||||
initially to see what results it can give you.
|
||||
|
||||
### Setting power profiles automatically
|
||||
|
||||
To make `power-profiles-daemon` actually useful and seamless, I like using a
|
||||
shell script that monitors the battery state and switches the power mode
|
||||
depending on certain conditions. I like placing my system-wide scripts into
|
||||
`/usr/local/bin`, so let's use: `/usr/local/bin/power-profiles-monitor`:
|
||||
|
||||
<!-- markdownlint-disable MD013 -->
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "You must run this script as root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BAT=$(echo /sys/class/power_supply/BAT*) # only supports single-battery systems
|
||||
BAT_STATUS="$BAT/status"
|
||||
BAT_CAP="$BAT/capacity"
|
||||
OVERRIDE_FLAG="/tmp/power-monitor-override"
|
||||
|
||||
POWER_SAVE_PERCENT=50 # Enter power-save mode if on bat and below this capacity
|
||||
|
||||
HAS_PERFORMANCE="$(powerprofilesctl list | grep "performance" || true)" # the || true ignores grep failing with non-zero code
|
||||
|
||||
# monitor loop
|
||||
prev=0
|
||||
while true; do
|
||||
# check if override is set
|
||||
if [ -f "$OVERRIDE_FLAG" ]; then
|
||||
echo "Override flag set, waiting for release"
|
||||
inotifywait -qq "$OVERRIDE_FLAG"
|
||||
continue
|
||||
fi
|
||||
|
||||
# read the current state
|
||||
status="$(cat "$BAT_STATUS")"
|
||||
capacity="$(cat "$BAT_CAP")"
|
||||
|
||||
if [[ $status == "Discharging" ]]; then
|
||||
if [[ $capacity -le $POWER_SAVE_PERCENT ]]; then
|
||||
profile="power-saver"
|
||||
else
|
||||
profile="balanced"
|
||||
fi
|
||||
else
|
||||
if [[ -n $HAS_PERFORMANCE ]]; then
|
||||
profile="performance"
|
||||
else
|
||||
profile="balanced"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Set the new profile
|
||||
if [[ "$profile" != "$prev" ]]; then
|
||||
echo -en "Setting power profile to ${profile}\n"
|
||||
powerprofilesctl set $profile
|
||||
prev=$profile
|
||||
fi
|
||||
|
||||
# wait for changes in status or capacity files
|
||||
# i.e. for the next power change event
|
||||
inotifywait -qq "$BAT_STATUS" "$BAT_CAP"
|
||||
done
|
||||
```
|
||||
|
||||
<!-- markdownlint-enable MD013 -->
|
||||
|
||||
> [!NOTE]
|
||||
> You will need `inotify-tools` package installed for the `inotifywait` command
|
||||
> to work.
|
||||
|
||||
As you can see, it's a pretty simple script, that will run forever, but spend
|
||||
most time just waiting for the battery status to change, re-running once it
|
||||
does.
|
||||
|
||||
We could now run this script manually, but that's not a great solution,
|
||||
instead, we can create a custom systemd service which will run it for us
|
||||
automatically. To do this, we'll create a new file:
|
||||
`/etc/systemd/system/power-profiles-monitor.service` with the following
|
||||
content:
|
||||
|
||||
```systemd
|
||||
[Unit]
|
||||
Description=Monitor the battery status, switching power profiles accordingly
|
||||
Wants=power-profiles-daemon.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/power-profiles-monitor
|
||||
Restart=on-failure
|
||||
Type=simple
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
```
|
||||
|
||||
With that, we can now enable our service:
|
||||
|
||||
```bash
|
||||
systemctl daemon-reload # make systemd aware of the new service
|
||||
systemctl enable --now power-profiles-monitor
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> You may have noticed that the script
|
||||
|
||||
## TLP
|
||||
|
||||
> [!IMPORTANT]
|
||||
> TLP is an alternative solution to handle power management, it cannot be used
|
||||
> in combination with `power-profiles-daemon`.
|
||||
|
||||
TODO: This section is work-in-progress, as I'm not using TLP right now.
|
||||
|
||||
If you wish to set up TLP, I'd suggest that you check out the official [TLP
|
||||
documentation](https://linrunner.de/tlp/introduction.html), alongside with a
|
||||
guide on achieving a similar profile switching behavior as
|
||||
`power-profiles-daemon` offers with it:
|
||||
[here](https://linrunner.de/tlp/faq/ppd.html). Additionally, there is an [Arch
|
||||
Linux Wiki page for TLP](https://wiki.archlinux.org/title/TLP).
|
||||
|
||||
## Sources
|
||||
|
||||
- <https://wiki.archlinux.org/title/Power_management>
|
||||
- <https://wiki.archlinux.org/title/Acpid>
|
||||
- <https://gitlab.freedesktop.org/upower/power-profiles-daemon>
|
||||
- <https://linrunner.de/tlp/introduction.html>
|
||||
- <https://linrunner.de/tlp/faq/ppd.html>
|
||||
- <https://wiki.archlinux.org/title/TLP>
|
152
guides/99_GREETD.md
Normal file
152
guides/99_GREETD.md
Normal file
|
@ -0,0 +1,152 @@
|
|||
# Greetd
|
||||
|
||||
This guide goes over how to setup `greetd`, which is a minimalistic Display
|
||||
Manager (DM) that starts right after boot and asks the user to log in.
|
||||
|
||||
A DM is useful for letting you pick which session you wish to load after
|
||||
logging in (e.g. which WM/DE), but also to provide a slightly nicer UI in
|
||||
comparison to the default `agetty` TTY based login screen.
|
||||
|
||||
Another neat feature that greetd offers is automatic login, which will allow
|
||||
you to skip the login process entirely, logging you in right after the boot.
|
||||
This can be useful if you're already typing in your LUKS encryption password
|
||||
each time after a boot, which already acts as a sufficient layer of protection
|
||||
against attackers trying to enter your system.
|
||||
|
||||
<!-- markdownlint-disable MD028 -->
|
||||
|
||||
> [!WARNING]
|
||||
> If you've set up TPM unlocking for your LUKS encryption, setting up automatic
|
||||
> login is not safe, unless you're using a TPM passphrase/PIN.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> If you're following while using my dotfiles, you will need to manually place
|
||||
> the greetd config from the repo into `/etc/greed/config.toml`. The
|
||||
> installation scripts don't do this, as many people prefer not using a
|
||||
> greeter.
|
||||
>
|
||||
> You will also need to follow the installation instructions to download greetd
|
||||
> and enable it.
|
||||
|
||||
<!-- markdownlint-enable MD028 -->
|
||||
|
||||
## Greetd + tuigreet
|
||||
|
||||
Since I prefer a minimalistic approach to most things in my system, I like to
|
||||
use a terminal based greeter. Greetd itself is just a daemon that supports
|
||||
various greeters. Most of these greeters are graphical, but there are terminal
|
||||
based ones too, most notably `tuigreet`, which works right from the TTY.
|
||||
|
||||
First, install and enable greetd, to make sure it gets started on boot.
|
||||
|
||||
```bash
|
||||
sudo pacman -S greetd greetd-tuigreet
|
||||
sudo systemctl enable greetd
|
||||
```
|
||||
|
||||
Now, we will want to define our greetd configuration in
|
||||
`/etc/greetd/config.toml`. There should already be a default configuraion that
|
||||
uses `agreety` greeter, which is similar to `agetty`, we'll want to change that
|
||||
to `tuigreet`, which in my opinion looks a lot better. We can use the following
|
||||
config:
|
||||
|
||||
<!-- markdownlint-disable MD013 -->
|
||||
|
||||
```toml
|
||||
[terminal]
|
||||
# The VT to run the greeter on. Can be "next", "current" or a number
|
||||
# designating the VT.
|
||||
vt = 1
|
||||
|
||||
# The default session, also known as the greeter.
|
||||
[default_session]
|
||||
|
||||
command = "tuigreet --time --remember --remember-user-session --asterisks --greeting 'Stop staring and log in already' --theme 'border=magenta;text=cyan;prompt=green;time=red;action=white;button=yellow;container=black;input=gray' --sessions /usr/share/wayland-sessions --xsessions /usr/share/xsessions --session-wrapper /usr/local/bin/greetd-session-wrapper --xsession-wrapper /usr/local/bin/greetd-session-wrapper startx /usr/bin/env"
|
||||
|
||||
# The user to run the command as. The privileges this user must have depends
|
||||
# on the greeter. A graphical greeter may for example require the user to be
|
||||
# in the `video` group.
|
||||
user = "greeter"
|
||||
```
|
||||
|
||||
<!-- markdownlint-enable MD013 -->
|
||||
|
||||
> [!NOTE]
|
||||
> I know the `tuigreet` command is really hard to orient in when written in a
|
||||
> single line like this, however, attempting to use a multi-line string doesn't
|
||||
> seem to work with greetd (even though it is a part of the TOML standard).
|
||||
> This issue has already been
|
||||
> [reported](https://lists.sr.ht/~kennylevinsen/greetd/<trinity-082b25fc-e1fa-4772-950c-d458f065024a-1648717080362@3c-app-mailcom-bs08>),
|
||||
> yet it doesn't seem like it was addressed.
|
||||
|
||||
You may have noticed that I've referred to a
|
||||
`/usr/local/bin/greetd-session-wrapper` script here, that's a custom script that
|
||||
I wrote to get greetd to run the command to start the WM/DE session within a
|
||||
running user shell (bash/zsh), so that the appropriate environment variables
|
||||
will be set when the WM is launched.
|
||||
|
||||
This is the content of that script:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# This is a helper wrapper script for greetd.
|
||||
#
|
||||
# It will run the session / application using the appropriate shell configured for
|
||||
# this user. That way, we can make sure all of the environment variables are set
|
||||
# before the WM/DE session is started.
|
||||
#
|
||||
# This is very important, as without it, variables for things like qt theme
|
||||
# will not be set, and applications executed by the WM/DE will not be themed properly.
|
||||
|
||||
script_name="$0"
|
||||
shell="$(getent passwd "$USER" | awk -F: '{print $NF}')"
|
||||
command=("$@")
|
||||
|
||||
exec "$shell" -c 'exec "$@"' "$script_name" "${command[@]}"
|
||||
```
|
||||
|
||||
With this configuration, you can now reboot and check whether greetd works
|
||||
properly. (You will still be asked for a password.)
|
||||
|
||||
```bash
|
||||
reboot
|
||||
```
|
||||
|
||||
If everything worked properly, you should've been presented with a custom
|
||||
tuigreet login screen after booting.
|
||||
|
||||
> [!TIP]
|
||||
> Feel free to adjust the `tuigreet` settings to your liking by editing the
|
||||
> `command` in the greetd settings. If you need a reference for what settings
|
||||
> are available, you can check out the
|
||||
> [`tuigreet`](https://github.com/apognu/tuigreet) project page.
|
||||
|
||||
## Configuring automatic Login
|
||||
|
||||
To configure automatic login, we'll need to modify the `greetd` settings in
|
||||
`/etc/greetd/config.toml` and add an initial session section:
|
||||
|
||||
```toml
|
||||
[terminal]
|
||||
# The VT to run the greeter on. Can be "next", "current" or a number
|
||||
# designating the VT.
|
||||
vt = 1
|
||||
|
||||
# Auto-login session, triggered right after boot.
|
||||
# If the user logs out, greetd will render the default session
|
||||
[initial_session]
|
||||
user = "itsdrike" # TODO: CHANGE THIS
|
||||
command = "/usr/local/bin/greetd-session-wrapper Hyprland"
|
||||
|
||||
# The default session, also known as the greeter.
|
||||
[default_session]
|
||||
|
||||
command = "tuigreet --time --remember --remember-user-session --asterisks --greeting 'Stop staring and log in already' --theme 'border=magenta;text=cyan;prompt=green;time=red;action=white;button=yellow;container=black;input=gray' --sessions /usr/share/wayland-sessions --xsessions /usr/share/xsessions --session-wrapper /usr/local/bin/greetd-session-wrapper --xsession-wrapper /usr/local/bin/greetd-session-wrapper startx /usr/bin/env"
|
||||
|
||||
# The user to run the command as. The privileges this user must have depends
|
||||
# on the greeter. A graphical greeter may for example require the user to be
|
||||
# in the `video` group.
|
||||
user = "greeter"
|
||||
```
|
76
guides/99_PRINTING.md
Normal file
76
guides/99_PRINTING.md
Normal file
|
@ -0,0 +1,76 @@
|
|||
# Printing
|
||||
|
||||
This guide explains how to set up printing and scanning on Arch Linux.
|
||||
|
||||
<!-- markdownlint-disable MD028 -->
|
||||
|
||||
> [!NOTE]
|
||||
> This guide is still WIP and isn't very informative, I wrote it just as a quick
|
||||
> reference for myself.
|
||||
|
||||
> [!NOTE]
|
||||
> This guide focuses on HP brand printers. If you have a printer from another
|
||||
> brand, you will not be able to fully follow it.
|
||||
|
||||
<!-- markdownlint-enable MD028 -->
|
||||
|
||||
## Installing
|
||||
|
||||
First, we'll need to install and enable `cups`, which is the printing daemon for
|
||||
Linux.
|
||||
|
||||
```bash
|
||||
sudo pacman -S --needed cups
|
||||
systemctl enable --now cups
|
||||
```
|
||||
|
||||
### HP printers
|
||||
|
||||
You'll want to use `hplip` if you're using an HP brand printer.
|
||||
|
||||
```bash
|
||||
sudo pacman -S --needed hplip
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> You will only want to use the hplip package for terminal based interactions.
|
||||
>
|
||||
> Hplip should support UI too, however, it uses Qt 4, for which the necessary
|
||||
> libraries are no longer shipped by pacman, as it's incredibly outdated. It is
|
||||
> technically possible to install these through the AUR, but due to the nature
|
||||
> of some of the dependencies for these outdated libraries, it would mean having
|
||||
> to install python2 and a bunch of related packages.
|
||||
>
|
||||
> Additionally, because hplip was written for very early python 3, you are
|
||||
> likely to see a lot of warnings when you run most commands. That said, the
|
||||
> commands should work, as these are just warnings.
|
||||
>
|
||||
> Aren't drivers written by big companies that have no clue about Linux just the
|
||||
> best?
|
||||
|
||||
To set up your printer, run:
|
||||
|
||||
```bash
|
||||
sudo hp-setup -i
|
||||
```
|
||||
|
||||
This will register the printer with CUPS and you should now be able to pick it
|
||||
in the printing dialog.
|
||||
|
||||
## Scanning
|
||||
|
||||
To get scanning support, you will need to have `sane`:
|
||||
|
||||
```bash
|
||||
sudo pacman -S sane
|
||||
```
|
||||
|
||||
If you're using `hplip`, you can now trigger a scan with the following command:
|
||||
|
||||
```bash
|
||||
hp-scan -o scan.png
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> If the specified filename ends with `.pdf`, hplip will store a PDF document
|
||||
> instead of a PNG image.
|
668
guides/99_THEMING.md
Normal file
668
guides/99_THEMING.md
Normal file
|
@ -0,0 +1,668 @@
|
|||
# Theming
|
||||
|
||||
This guide will go over setting up Qt and GTK themes on Arch Linux.
|
||||
|
||||
My preferred setup uses:
|
||||
|
||||
- [BreezeX-RosePine-Linux](https://github.com/rose-pine/cursor) cursor theme,
|
||||
size 24.
|
||||
- [Papirus-Dark](https://github.com/catppuccin/papirus-folders) icon theme from
|
||||
catppuccin papirus folders, specifically the blue accent & mocha flavor
|
||||
variant.
|
||||
- The default font of my choice is [Noto
|
||||
Sans](https://fonts.google.com/noto/specimen/Noto+Sans), size 10
|
||||
- The default monospace font of my choice is [Monaspace
|
||||
Krypton](https://monaspace.githubnext.com/)
|
||||
- For GTK theme, I'm using
|
||||
[Tokyonight-Dark](https://github.com/Fausto-Korpsvart/Tokyonight-GTK-Theme).
|
||||
- For QT theme, I'm using
|
||||
[Catppuccin-Mocha-Blue](https://github.com/catppuccin/Kvantum) kvantum theme.
|
||||
|
||||
> [!NOTE]
|
||||
> My dotfiles already include most of the necessary theme configuration files,
|
||||
> so if you're using them, you can skip a lot of the steps I mention here. This
|
||||
> guide assumes a completely un-themed system, to make it easy for anyone to
|
||||
> follow.
|
||||
>
|
||||
> If there is something that you're expected to do even if you've copied over
|
||||
> all of the configuration files from my dotfiles repo, it will be explicitly
|
||||
> mentioned in an _important_ markdown block.
|
||||
|
||||
## Packages
|
||||
|
||||
First, we'll install all the required packages:
|
||||
|
||||
```bash
|
||||
paru -S --needed \
|
||||
rose-pine-cursor \
|
||||
papirus-folders-catppuccin-git \
|
||||
noto-fonts otf-monaspace \
|
||||
tokyonight-gtk-theme-git \
|
||||
kvantum kvantum-qt5 qt5ct qt6ct kvantum-theme-catppuccin-git
|
||||
```
|
||||
|
||||
## Dconf / Gsettings
|
||||
|
||||
Dconf is a low-level configuration system that works through D-Bus, serving as
|
||||
backend to GSettings. It's a simple key-based config systems, with the keys
|
||||
existing in an unstructured database.
|
||||
|
||||
You can use the `dconf` command manually to set specific keys to given values,
|
||||
but it's often more a better idea to use `gsettings`, which provide some
|
||||
abstractions and does consistency checking, but ultimately it will just store
|
||||
the configured values into the `dconf` database.
|
||||
|
||||
Dconf is used by a lot of applications for various things, but a lot of the
|
||||
dconf settings are related to theming and it's crucial that we set them, as some
|
||||
applications will follow these instead of the configuration files.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> You will need to perform this step even if you're using my dotfiles. The
|
||||
> dconf database is not a part of my dotfiles, so these values won't be set.
|
||||
|
||||
```bash
|
||||
# Global configuration that tells applications to prefer dark mode
|
||||
gsettings set org.gnome.desktop.interface color-scheme prefer-dark
|
||||
|
||||
# GTK theme
|
||||
gsettings set org.gnome.desktop.interface gtk-theme Tokyonight-Dark
|
||||
|
||||
# Font settings
|
||||
gsettings set org.gnome.desktop.interface font-name 'Noto Sans 10'
|
||||
gsettings set org.gnome.desktop.interface document-font-name 'Noto Sans 10'
|
||||
gsettings set org.gnome.desktop.interface monospace-font-name 'Source Code Pro 10'
|
||||
|
||||
# Cursor settings
|
||||
gsettings set org.gnome.desktop.interface cursor-theme 'BreezeX-RosePine-Linux'
|
||||
gsettings set org.gnome.desktop.interface cursor-size 24
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> You can find all registered dconf schemas with `gsettings list-schemas`. To
|
||||
> include the keys, you can `gsettings list-recursively`.
|
||||
>
|
||||
> You might want to set some of these according to your preferences.
|
||||
|
||||
## XSettings
|
||||
|
||||
Similarly to dconf/gsettings specification, there's also an XSETTINGS
|
||||
specification, that is used by some Xorg applications (most notably GTK, Java
|
||||
and Wine based apps). It is less useful on Wayland, but since a lot of
|
||||
applications still don't have native wayland support, it may be worth setting
|
||||
up anyways. XWayland applications may still depend on this.
|
||||
|
||||
Applications that rely on this specification will ask for the settings from the
|
||||
Xorg server, which itself gets them from a daemon service. On GNOME desktop,
|
||||
this would be `gnome-settings-daemon`, but anywhere else, you'll want to use
|
||||
[`xsettingsd`](https://codeberg.org/derat/xsettingsd), which is a lightweight
|
||||
alternative.
|
||||
|
||||
<!-- markdownlint-disable MD028 -->
|
||||
|
||||
> [!NOTE]
|
||||
> This part of the guide is optional, you don't have to set up xsettings, most
|
||||
> applications will work just fine without it.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> If you do wish to set up xsettings, you will need to follow these
|
||||
> instructions, even if you've populated your system with the configuration
|
||||
> files from my dotifiles, as it requires installing a package and activating a
|
||||
> systemd service.
|
||||
|
||||
<!-- markdownlint-enable MD028 -->
|
||||
|
||||
First, you will want to install `xsettingd` package and activate the systemd
|
||||
service, so that applications can ask for this daemon a specific setting:
|
||||
|
||||
```bash
|
||||
pacman -S xsettingsd
|
||||
systemctl --user enable --now xsettingsd
|
||||
```
|
||||
|
||||
These settings can control various things, but for us, we'll focus on the
|
||||
theming. XSettings are configured simply through a config file in:
|
||||
`~/.config/xsettingsd/xsettingsd.conf`.
|
||||
|
||||
To configure theming in xsettings, you can put the following settings into your
|
||||
`xsettingsd.conf` file:
|
||||
|
||||
```conf
|
||||
Net/ThemeName "Tokyonight-Dark"
|
||||
Net/IconThemeName "Papirus-Dark"
|
||||
Gtk/CursorThemeName "BreezeX-RosePine-Linux"
|
||||
Net/EnableEventSounds 1
|
||||
EnableInputFeedbackSounds 0
|
||||
Xft/Antialias 1
|
||||
Xft/Hinting 1
|
||||
Xft/HintStyle "hintslight"
|
||||
Xft/RGBA "rgb"
|
||||
```
|
||||
|
||||
## GTK
|
||||
|
||||
> [!TIP]
|
||||
> We'll be setting things up manually, however, if you wish, you can also use
|
||||
> [`nwg-look`](https://github.com/nwg-piotr/nwg-look) to configure GTK from a
|
||||
> graphical settings application. Do note though that by default, it doesn't
|
||||
> support GTK 4 theming (see: [this github
|
||||
> issue](https://github.com/nwg-piotr/nwg-look/issues/22)).
|
||||
>
|
||||
> `nwg-look` is inspired by the more popular `lxappearance`, however, it is
|
||||
> made for native wayland. That said, either will work, so you can also try
|
||||
> `lxappearance` if you wish, even on wayland.
|
||||
|
||||
### GTK 2
|
||||
|
||||
For GTK 2, we'll first want to change the location of the `gtkrc` configuration
|
||||
file, to follow proper XDG base directory specification and avoid it cluttering
|
||||
`$HOME`. To do this, we'll need to set the following environment variable to be
|
||||
exported by your shell:
|
||||
|
||||
```bash
|
||||
export GTK2_RC_FILES="$XDG_CONFIG_HOME/gtk-2.0/gtkrc":"$XDG_CONFIG_HOME/gtk-2.0/gtkrc.mine"
|
||||
```
|
||||
|
||||
We'll now create `~/.config/gtk-2.0` directory, and a `gtkrc` file inside of it,
|
||||
with the following content:
|
||||
|
||||
```text
|
||||
gtk-theme-name = "Tokyonight-Dark"
|
||||
gtk-icon-theme-name = "Papirus-Dark"
|
||||
gtk-cursor-theme-name = "BreezeX-RosePine-Linux"
|
||||
gtk-cursor-theme-size = 24
|
||||
gtk-font-name = "Noto Sans 10"
|
||||
gtk-button-images=1
|
||||
gtk-menu-images=1
|
||||
gtk-enable-event-sounds=0
|
||||
gtk-enable-input-feedback-sounds=0
|
||||
gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
|
||||
gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ
|
||||
gtk-xft-antialias=1
|
||||
gtk-xft-hinting=1
|
||||
gtk-xft-hintstyle="hintslight"
|
||||
gtk-xft-rgba="rgb"
|
||||
```
|
||||
|
||||
### GTK 3
|
||||
|
||||
For GTK 3, we'll put the following into `~/.config/gtk-3.0/settings.ini`:
|
||||
|
||||
```conf
|
||||
[Settings]
|
||||
gtk-application-prefer-dark-theme=true
|
||||
gtk-theme-name=Tokyonight-Dark
|
||||
gtk-icon-theme-name=Papirus-Dark
|
||||
gtk-cursor-theme-name=BreezeX-RosePine-Linux
|
||||
gtk-cursor-theme-size=24
|
||||
gtk-font-name=Noto Sans 10
|
||||
gtk-enable-animations=true
|
||||
gtk-button-images=1
|
||||
gtk-menu-images=1
|
||||
gtk-enable-event-sounds=0
|
||||
gtk-enable-input-feedback-sounds=0
|
||||
gtk-error-bell=0
|
||||
gtk-decoration-layout=appmenu:none
|
||||
gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
|
||||
gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ
|
||||
gtk-xft-antialias=1
|
||||
gtk-xft-hinting=1
|
||||
gtk-xft-hintstyle=hintslight
|
||||
```
|
||||
|
||||
### GTK 4
|
||||
|
||||
For GTK 4, we'll put the following into `~/.config/gtk-4.0/settings.ini`:
|
||||
|
||||
```conf
|
||||
[Settings]
|
||||
gtk-application-prefer-dark-theme=true
|
||||
gtk-theme-name=Tokyonight-Dark
|
||||
gtk-icon-theme-name=Papirus-Dark
|
||||
gtk-cursor-theme-name=BreezeX-RosePine-Linux
|
||||
gtk-cursor-theme-size=24
|
||||
gtk-font-name=Noto Sans 10
|
||||
gtk-enable-event-sounds=0
|
||||
gtk-enable-input-feedback-sounds=0
|
||||
gtk-error-bell=0
|
||||
gtk-decoration-layout=appmenu:none
|
||||
gtk-xft-antialias=1
|
||||
gtk-xft-hinting=1
|
||||
gtk-xft-hintstyle=hintslight
|
||||
```
|
||||
|
||||
For `libadwaita` based GTK 4 applications, you will need to force a GTK theme
|
||||
with an environment variable, so you will also want to export the following:
|
||||
|
||||
```bash
|
||||
export GTK_THEME="Tokyonight-Dark"
|
||||
```
|
||||
|
||||
<!-- markdownlint-disable MD028 -->
|
||||
|
||||
> [!WARNING]
|
||||
> This will only work if your theme has GTK 4 support.
|
||||
|
||||
> [!TIP]
|
||||
> As an alternative to exporting the `GTK_THEME` env var like this, you can
|
||||
> also install `libadwaita-without-adwaita-git` AUR package, which contains a
|
||||
> patch to prevent GTK from overriding the system theme.
|
||||
>
|
||||
> Another option would be to import the theme in `gtk.css`: `~/.config/gtk-4.0/gtk.css`:
|
||||
>
|
||||
> ```css
|
||||
> /**
|
||||
> * GTK 4 reads the theme configured by gtk-theme-name, but ignores it.
|
||||
> * It does however respect user CSS, so import the theme from here.
|
||||
> **/
|
||||
> @import url("file:///usr/share/themes/Tokyonight-Dark/gtk-4.0/gtk.css");
|
||||
> ```
|
||||
|
||||
<!-- markdownlint-enable MD028 -->
|
||||
|
||||
### Make GTK follow XDG portal settings
|
||||
|
||||
Certain things, such as dialogs or file-pickers can be controlled via XDG
|
||||
desktop portals, however, by default, GTK apps will not follow these settings.
|
||||
To force them into doing so, you can export an environment variable:
|
||||
|
||||
```bash
|
||||
export GTK_USE_PORTAL=1
|
||||
```
|
||||
|
||||
## Qt
|
||||
|
||||
This section goes over configuring QT styles for qt 5 and qt 6.
|
||||
|
||||
### Kvantum
|
||||
|
||||
I like using `kvantum` to configure QT themes. Kvantum is an SVG style
|
||||
customizer/engine, for which there's a bunch of plugins. It then turns these
|
||||
plugins / kvantum themes into full QT themes. For theme creators, it simplifies
|
||||
making a full QT theme.
|
||||
|
||||
> [!NOTE]
|
||||
> Kvantum will only be useful for you if you actually want to use a kvantum
|
||||
> theme. If you wish to use a full QT theme that doesn't need kvantum, you can
|
||||
> skip this and instead achieve the same with qtct. (I'll say a bit more about
|
||||
> qtct in icon theme section.)
|
||||
|
||||
Kvantum works as a Qt style instead of a Qt platform theme. To set kvantum for
|
||||
all Qt applications, you can export the following env variable:
|
||||
|
||||
```bash
|
||||
export QT_STYLE_OVERRIDE=kvantum
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> For backwards compatibility, in addition to the `kvantum` package, you will
|
||||
> also need `kvantum-qt5` (`kvantum` works with qt6). If you followed the
|
||||
> initial install instructions, you will have both installed already.
|
||||
|
||||
### Theme
|
||||
|
||||
We will now want to tell kvantum which theme to use. To do this, we will need to
|
||||
create a settings file for Kvantum in `~/.config/Kvantum/kvantum.kvconfig`, with
|
||||
the following content:
|
||||
|
||||
```conf
|
||||
[General]
|
||||
theme=catppuccin-mocha-blue
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> The system-wide kvantum themes are located in `/usr/share/Kvantum`. The theme
|
||||
> variable has to match the directory name of one of these themes.
|
||||
>
|
||||
> If you wish to use a custom theme that isn't available as a package, you can
|
||||
> also add it as a user theme directly into `~/.config/Kvantum/`.
|
||||
|
||||
### Icon theme & qtct
|
||||
|
||||
As a theme qt engine, kvantum can't handle icons. For those, we will use qtct
|
||||
platform theme.
|
||||
|
||||
> [!NOTE]
|
||||
> You will need to install `qt5ct` & `qt6ct` packages. These will also be
|
||||
> installed already if you followed the initial install command though.
|
||||
|
||||
Now we'll set the QT platform theme through an environment variable:
|
||||
|
||||
```bash
|
||||
export QT_QPA_PLATFORMTHEME="qt5ct" # keep this value even for qt6ct
|
||||
```
|
||||
|
||||
Finally, we can add a qtct configuration to use our preferred icon theme:
|
||||
|
||||
`~/.config/qt5ct/qt5ct.conf`:
|
||||
|
||||
```conf
|
||||
[Appearance]
|
||||
icon_theme=Papirus-Dark
|
||||
```
|
||||
|
||||
Same thing for `~/.config/qt6ct/qt6ct.conf`.
|
||||
|
||||
> [!NOTE]
|
||||
> qtct is a platform theme and it can do a lot more than just set the icon
|
||||
> theme, however, we chose kvantum to serve as our style, so we don't need
|
||||
> anything else from qtct.
|
||||
>
|
||||
> If you wish to instead use qtct for picking the qt style, unset the
|
||||
> `QT_STYLE_OVERRIDE` variable and pick your theme in both `qt5ct` & `qt6ct`
|
||||
> applications. This will modify the `qt5ct.conf` and the qt 6 variant.
|
||||
|
||||
### Additional things
|
||||
|
||||
There are some extra things that you'll probably want to set. To do so, we will
|
||||
yet again use more environment variables. Specifically:
|
||||
|
||||
```bash
|
||||
# Enables automatic scaling, based on the monitor's pixel density.
|
||||
export QT_AUTO_SCREEN_SCALE_FACTOR="1"
|
||||
# Run QT applications using the wayland plugin, falling back to xcb (X11) plugin
|
||||
export QT_QPA_PLATFORM="wayland;xcb"
|
||||
# Disable client side decorations
|
||||
export QT_WAYLAND_DISABLE_WINDOWDECORATION="1"
|
||||
```
|
||||
|
||||
## Cursor
|
||||
|
||||
### XCursor
|
||||
|
||||
XCursor is the default cursor format for cursor themes. Even though the name
|
||||
might imply that it's connected to X11, it will work just fine on wayland too.
|
||||
|
||||
To select a cursor theme to be used, you'll want to export the following
|
||||
environment variables:
|
||||
|
||||
```bash
|
||||
export XCURSOR_THEME="BreezeX-RosePine-Linux"
|
||||
export XCURSOR_SIZE="24"
|
||||
```
|
||||
|
||||
Additionally, you might want to also modify/set `XCURSOR_PATH`, to make sure
|
||||
that it includes `~/.local/share/icons`, as otherwise, xcursor will not look
|
||||
here for cursor themes by default on some DEs/WMs.
|
||||
|
||||
```bash
|
||||
export XCURSOR_PATH=$XCURSOR_PATH${XCURSOR_PATH:+:}~/.local/share/icons
|
||||
```
|
||||
|
||||
### Default cursor config
|
||||
|
||||
The cursor theme name "default" is used by an application if it cannot pick up
|
||||
on a configuration. The default cursor theme can live in:
|
||||
`~/.local/share/icons/default` or `/usr/share/icons/default`.
|
||||
|
||||
To set the default cursor for your user, create a
|
||||
`~/.local/share/icons/default/index.theme` file with the following:
|
||||
|
||||
```conf
|
||||
[Icon Theme]
|
||||
Name=Default
|
||||
Comment=Default Cursor Theme
|
||||
Inherits=BreezeX-RosePine-Linux
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> Alternatively, we could also symlink the cursor theme into the `default`
|
||||
> directory, like so:
|
||||
>
|
||||
> ```bash
|
||||
> ln -s /usr/share/icons/BreezeX-RosePine-Linux/ ~/.local/share/icons/default
|
||||
> ```
|
||||
>
|
||||
> That said, I prefer using `Inherits` here, as it allows me to easily store the
|
||||
> default cursor config in my dotfiles.
|
||||
|
||||
### Cursor config for GTK
|
||||
|
||||
You may have noticed earlier that we've already touched on specifying the cursor
|
||||
configuration for GTK in the gtkrc/gtk settings, this is done via the
|
||||
`gtk-cursor-theme-name` and `gtk-cursor-theme-size` setting options. Because of
|
||||
that, there's no need to do anything extra to get GTK apps to use the correct
|
||||
cursor theme.
|
||||
|
||||
### Cursor config for Qt
|
||||
|
||||
There is no Qt configuration for cursors. Qt programs may pick up a cursor theme
|
||||
from the desktop environment (server-side cursors), X resources, or lastly the
|
||||
"default" cursor theme.
|
||||
|
||||
### Hyprcursor
|
||||
|
||||
[hyprcursor](https://github.com/hyprwm/hyprcursor) is a new and efficient a
|
||||
cursor format, that allow for SVG based cursors, resulting in a much better
|
||||
scaling experience and more space-efficient themes.
|
||||
|
||||
Hyprcursor is supported out of the box by Hyprland, so if you're using Hyprland,
|
||||
you can benefit from it. That said, this part is entirely optional and you can
|
||||
just stick with xcursor if you wish.
|
||||
|
||||
If you do want to use hyprcursor, you will want to install [hyprcursor version
|
||||
of the rose-pine-cursor
|
||||
theme](https://github.com/ndom91/rose-pine-cursor-hyprcursor). You can simply
|
||||
git clone this repository right into `~/.local/share/icons` (sadly, there isn't
|
||||
an AUR package available at this time):
|
||||
|
||||
```bash
|
||||
cd ~/.local/share/icons
|
||||
git clone https://github.com/ndom91/rose-pine-cursor-hyprcursor
|
||||
```
|
||||
|
||||
Finally, you will want to set the following environment variables:
|
||||
|
||||
```bash
|
||||
export HYPRCURSOR_THEME="rose-pine-hyprcursor"
|
||||
export HYPRCURSOR_SIZE="24"
|
||||
```
|
||||
|
||||
Alternatively, you can also set these variables right from your hyprland config:
|
||||
|
||||
```hyprlang
|
||||
env = HYPRCURSOR_THEME,rose-pine-hyprcursor
|
||||
env = HYPRCURSOR_SIZE,24
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> Make sure to keep the existing xcursor environment variables and themes, as
|
||||
> although many apps do support server-side cursors (e.g. Qt, Chromium,
|
||||
> Electron, ...), some still don't (looking at you GTK, but also some other,
|
||||
> less common things). These applications will then fall back to XCursor (unless
|
||||
> they have built-in hyprcursor support, which is rare).
|
||||
>
|
||||
> I would therefore also recommend leaving the default theme point to the
|
||||
> XCursor theme, not to a hyprcursor theme.
|
||||
|
||||
## Fonts
|
||||
|
||||
Some applications use `gsettings`/`dconf` to figure out what font to use. We've
|
||||
already configured these settings, so those applications should pick up which
|
||||
font to use correctly.
|
||||
|
||||
Other applications will use GTK config to figure out the default fonts. We've
|
||||
configured this earlier too. (Note that GTK config doesn't support specifying a
|
||||
monospace font).
|
||||
|
||||
The rest of the applications will use generic font family names ("standard"
|
||||
fonts), as defined through `fontconfig`.
|
||||
|
||||
Applications also often provide configuration files where you can define which
|
||||
font you wish to be using, so sometimes, you will need to set the font on a
|
||||
per-application basis. We will not cover this, as each application is different.
|
||||
|
||||
### Installing fonts
|
||||
|
||||
In the installation instructions above, I did specify the 2 default font
|
||||
packages that I wanted to use for my system. That said, I did not specify an
|
||||
emoji font there and there are many fonts that are just useful to have on the
|
||||
system, for things like text editing. The command below will install most of the
|
||||
fonts that you might need:
|
||||
|
||||
```bash
|
||||
paru -S --needed \
|
||||
libxft xorg-font-util \
|
||||
ttf-joypixels otf-jost lexend-fonts-git ttf-sarasa-gothic \
|
||||
ttf-roboto ttf-work-sans ttf-comic-neue \
|
||||
gnu-free-fonts tex-gyre-fonts ttf-liberation otf-unifont \
|
||||
inter-font ttf-lato ttf-dejavu noto-fonts noto-fonts-cjk \
|
||||
noto-fonts-emoji ttf-material-design-icons-git \
|
||||
ttf-font-awesome ttf-twemoji otf-openmoji \
|
||||
adobe-source-code-pro-fonts adobe-source-han-mono-otc-fonts \
|
||||
adobe-source-sans-fonts ttf-jetbrains-mono otf-monaspace \
|
||||
ttf-ms-fonts
|
||||
```
|
||||
|
||||
#### Nerd fonts
|
||||
|
||||
I have intentionally left out the `nerd-fonts` package from the above command,
|
||||
as it is fairly large (about 8 gigabytes). If you wish, you can install it, as
|
||||
it does contain some pretty useful fonts, however, if this package is too big
|
||||
for you, you can instead install the fonts individually, as arch does ship all
|
||||
nerd fonts in the package manager individually.
|
||||
|
||||
To install all nerd fonts, you can simply:
|
||||
|
||||
```bash
|
||||
paru -S --needed nerd-fonts
|
||||
```
|
||||
|
||||
If you instead wish to only install specific nerd fonts, you can use the
|
||||
following command. Note that you may want to add more fonts from nerd-fonts.
|
||||
|
||||
```bash
|
||||
paru -S --needed \
|
||||
ttf-firacode-nerd otf-firamono-nerd ttf-iosevka-nerd ttf-nerd-fonts-symbols \
|
||||
ttf-hack-nerd ttf-heavydata-nerd ttf-gohu-nerd
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> If you wish to use all of nerd-fonts, you will need to run the above command
|
||||
> even after going through the install scripts from my dotfiles, as they only
|
||||
> install specific nerd fonts (the above).
|
||||
|
||||
### Setting standard fonts
|
||||
|
||||
These standard fonts are:
|
||||
|
||||
- `sans-serif`: Standard font for regular text (articles, menus, ...)
|
||||
- `serif`: Like sans-serif, but pure sans fonts shouldn't have the decorative
|
||||
lines or tapers (also known as "tails" or "feet"). Note that these should fall
|
||||
back to `sans-serif` if unset.
|
||||
- `monospace`: Standard font for fixed-width fonts (text editors, calculators,
|
||||
...)
|
||||
- `emoji`: Standard font for emoji glyphs
|
||||
|
||||
It is possible to register multiple fonts for the standard font, ordered by
|
||||
priorities. That way, if the first font isn't found, or it doesn't contain the
|
||||
given glyph, the search will fall back to the next font in line.
|
||||
|
||||
To set a standard font, you will need to create a fontconfig configuration file.
|
||||
You can do this on a per-user basis, in `~/.config/fontconfig/fonts.conf` (or
|
||||
`~/.config/fontconfig/conf.d/`) or system-wide in `/etc/fonts/local.conf` (don't
|
||||
modify `/etc/fonts/fonts.conf` nor the files in `/etc/fonts/conf.d`, these are
|
||||
managed by the package manager and could get overwritten). Note that the user
|
||||
font settings will take priority if there are overlapping settings.
|
||||
|
||||
I prefer using the system-wide settings (`/etc/fonts/local.conf`):
|
||||
|
||||
```xml
|
||||
<?xml version='1.0'?>
|
||||
<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
|
||||
<fontconfig>
|
||||
<alias binding="same">
|
||||
<family>sans-serif</family>
|
||||
<prefer>
|
||||
<family>Noto Sans</family>
|
||||
<family>Jost</family>
|
||||
<family>Lexend</family>
|
||||
<family>Iosevka Nerd Font</family>
|
||||
<family>Symbols Nerd Font</family>
|
||||
<family>Noto Color Emoji</family>
|
||||
</prefer>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>serif</family>
|
||||
<prefer>
|
||||
<family>Noto Serif</family>
|
||||
<family>Iosevka Nerd Font</family>
|
||||
<family>Symbols Nerd Font</family>
|
||||
<family>Noto Color Emoji</family>
|
||||
</prefer>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>monospace</family>
|
||||
<prefer>
|
||||
<family>Monaspace Krypton</family>
|
||||
<family>Source Code Pro Medium</family>
|
||||
<family>Source Han Mono</family>
|
||||
<family>Iosevka Nerd Font</family>
|
||||
<family>Symbols Nerd Font</family>
|
||||
<family>Noto Color Emoji</family>
|
||||
</prefer>
|
||||
</alias>
|
||||
|
||||
<alias binding="same">
|
||||
<family>emoji</family>
|
||||
<prefer>
|
||||
<family>Noto Color Emoji</family>
|
||||
<family>Iosevka Nerd Font</family>
|
||||
<family>Symbols Nerd Font</family>
|
||||
<family>Noto Color Emoji</family>
|
||||
</prefer>
|
||||
</alias>
|
||||
</fontconfig>
|
||||
```
|
||||
|
||||
You will now need to rebuild the font cache with:
|
||||
|
||||
```bash
|
||||
fc-cache -vf
|
||||
```
|
||||
|
||||
### Disable Caskaydia Cove Nerd Font
|
||||
|
||||
For some reason, having the Caskaydia font installed was causing some issues
|
||||
with other fonts for me. Caskaydia comes from `nerd-fonts`, so if you installed
|
||||
them, you might want to follow along with this too, if you're also facing
|
||||
issues. I'm honestly not sue why that is, however, all that's needed to solve it
|
||||
is disabling this font entirely. To do so, add the following to your
|
||||
`fontconfig` config:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
|
||||
|
||||
<fontconfig>
|
||||
<selectfont>
|
||||
<rejectfont>
|
||||
<glob>/usr/share/fonts/nerd-fonts-git/TTF/Caskaydia*</glob>
|
||||
</rejectfont>
|
||||
</selectfont>
|
||||
</fontconfig>
|
||||
```
|
||||
|
||||
### Font Manager
|
||||
|
||||
To preview the installed fonts, I like using `font-manager`:
|
||||
|
||||
```bash
|
||||
paru -S --needed font-manager
|
||||
```
|
||||
|
||||
## Sources
|
||||
|
||||
- <https://askubuntu.com/questions/22313/what-is-dconf-what-is-its-function-and-how-do-i-use-it>
|
||||
- <https://man.archlinux.org/man/dconf.1.en>
|
||||
- <https://wiki.archlinux.org/title/Xsettingsd>
|
||||
- <https://www.reddit.com/r/gnome/comments/wt8oml/is_gnomesettingsdaemon_no_longer_a_program_i_can/>
|
||||
- <https://wiki.archlinux.org/title/GTK>
|
||||
- <https://wiki.archlinux.org/title/XDG_Base_Directory>
|
||||
- <https://wiki.archlinux.org/title/Uniform_look_for_Qt_and_GTK_applications>
|
||||
- <https://wiki.archlinux.org/title/Qt>
|
||||
- <https://wiki.archlinux.org/title/Cursor_themes>
|
||||
- <https://wiki.hyprland.org/Hypr-Ecosystem/hyprcursor/>
|
||||
- <https://wiki.archlinux.org/title/Font_configuration>
|
||||
- <https://bbs.archlinux.org/viewtopic.php?id=275434>
|
|
@ -1,414 +0,0 @@
|
|||
# Installation
|
||||
|
||||
This is a full Arch Linux installation guide, from live cd to a working OS.
|
||||
This installation includes steps for full disk encryption, and sets up the
|
||||
system with some basic tools and my zsh configuration.
|
||||
|
||||
## Partition, format and mount the disks
|
||||
|
||||
This will depend on your setup, following are the commands I used for my
|
||||
specific setup as a reference, however you'll very like want a different
|
||||
disk structure, and you probably won't even have the drives in the same
|
||||
configuration as I do.
|
||||
|
||||
Create partitions for the drives
|
||||
|
||||
```bash
|
||||
fdisk /dev/nvme0n1
|
||||
# Create new GPT table and make 3 partitions
|
||||
# first for boot (1G), second for swap (16G),
|
||||
# third for btrfs (root + /home + data) (rest of the space)
|
||||
|
||||
fdisk /dev/nvme0n2
|
||||
# Create a single partition for btrfs data
|
||||
```
|
||||
|
||||
Format partitions that shouldn't be encrypted
|
||||
|
||||
```bash
|
||||
mkfs.fat -F 32 /dev/nvme0n1p1
|
||||
fatlabel /dev/nvme0n1p1 EFI
|
||||
mkswap -L SWAP /dev/nvme0n1p2
|
||||
```
|
||||
|
||||
Format drives using LUKS for encryption and open them to mapper devices
|
||||
|
||||
```bash
|
||||
cryptsetup luksFormat --type luks2 --label ARCH_LUKS /dev/nvme0n1p3
|
||||
cryptsetup luksFormat --type luks2 --label DATA /dev/nvme0n2p1
|
||||
|
||||
cryptsetup luksOpen /dev/disk/by-label/ARCH_LUKS cryptroot
|
||||
cryptsetup luksOpen /dev/disk/by-label/DATA cryptdata
|
||||
```
|
||||
|
||||
Create BTRFS filesystem on the encrypted drives
|
||||
|
||||
```bash
|
||||
mkfs.btrfs -f -L ARCH /dev/mapper/cryptroot
|
||||
mkfs.btrfs -f -L DATA /dev/mapper/cryptdata
|
||||
```
|
||||
|
||||
Mount btrfs and create subvolumes
|
||||
|
||||
```bash
|
||||
# Cryptroot
|
||||
# - We set `noatime` to disable updating of the file access time
|
||||
# every time a file is read. This is done for performance improvements,
|
||||
# especially on SSDs, and we don't really need to know this information
|
||||
# anyway.
|
||||
# - We set `compress=zstd:1` to enable level 1 zstd compression (lowest),
|
||||
# which still provides quite fast read/write speeds, while saving some space.
|
||||
mount -o noatime,compress=zstd:1 /dev/mapper/cryptroot /mnt
|
||||
btrfs subvolume create /mnt/@ # / (root)
|
||||
btrfs subvolume create /mnt/@home # /home
|
||||
btrfs subvolume create /mnt/@log # /var/log
|
||||
btrfs subvolume create /mnt/@cache # /var/cache
|
||||
btrfs subvolume create /mnt/@tmp # /tmp
|
||||
btrfs subvolume create /mnt/@data # /data
|
||||
btrfs subvolume create /mnt/@snapshots
|
||||
umount /mnt
|
||||
|
||||
# cryptdata
|
||||
# - We use same options for mounting the root btrfs drive as
|
||||
# we did for cryptroot here, however we will use a bigger compression
|
||||
# rate for the individual subvolumes when mounting them.
|
||||
mount -o noatime,compress=zstd:1 /dev/mapper/cryptdata /mnt
|
||||
btrfs subvolume create /mnt/@data # /data2
|
||||
btrfs subvolume create /mnt/@backups # /backups
|
||||
btrfs subvolume create /mnt/@snapshots
|
||||
umount /mnt
|
||||
```
|
||||
|
||||
Mount the subvolumes and drives
|
||||
|
||||
```bash
|
||||
# cryptroot btrfs subvolumes
|
||||
mount -o defaults,noatime,compress=zstd:1,subvol=@ /dev/mapper/cryptroot /mnt
|
||||
mount -o defaults,noatime,compress=zstd:1,subvol=@home /dev/mapper/cryptroot /mnt/home --mkdir
|
||||
mount -o defaults,noatime,compress=zstd:2,subvol=@log /dev/mapper/cryptroot /mnt/var/log --mkdir
|
||||
mount -o defaults,noatime,compress=zstd:3,subvol=@cache /dev/mapper/cryptroot /mnt/var/cache --mkdir
|
||||
mount -o defaults,noatime,compress=no,subvol=@tmp /dev/mapper/cryptroot /mnt/tmp --mkdir
|
||||
mount -o defaults,noatime,compress=zstd:5,subvol=@data /dev/mapper/cryptroot /mnt/data --mkdir
|
||||
# cryptdata btrfs subvolumes
|
||||
mount -o defaults,noatime,compress=zstd:5,subvol=@data /dev/mapper/cryptdata /mnt/data2 --mkdir
|
||||
mount -o defaults,noatime,compress=zstd:10,subvol=@backups /dev/mapper/cryptdata /mnt/backups --mkdir
|
||||
# physical partitions
|
||||
mount /dev/disk/by-label/EFI /mnt/efi --mkdir
|
||||
mkdir /mnt/efi/arch-1
|
||||
mount --bind /mnt/efi/arch-1 /mnt/boot --mkdir
|
||||
swapon /dev/disk/by-label/SWAP
|
||||
```
|
||||
|
||||
## Base installation
|
||||
|
||||
```bash
|
||||
reflector --save /etc/pacman.d/mirrorlist --latest 10 --protocol https --sort rate
|
||||
pacstrap -K /mnt base linux linux-firmware linux-headers amd-ucode # or intel-ucode
|
||||
genfstab -U /mnt >> /mnt/etc/fstab
|
||||
# Note: We'll need to edit fstab later on, to use UUIDs, and to set proper compression levels
|
||||
# as the generated options will just use zstd:1 everywhere, the final fstab is shown late.
|
||||
# during bootloader config
|
||||
arch-chroot /mnt
|
||||
```
|
||||
|
||||
Configure essentials
|
||||
|
||||
```bash
|
||||
pacman -S git btrfs-progs neovim
|
||||
ln -sf /usr/share/zoneinfo/CET /etc/localtime
|
||||
hwclock --systohc
|
||||
sed -i 's/^#en_US.UTF-8/en_US.UTF-8/g' /etc/locale.gen
|
||||
echo "LANG=en_US.UTF-8" > /etc/locale.conf
|
||||
locale-gen
|
||||
echo "pc" > /etc/hostname
|
||||
passwd
|
||||
```
|
||||
|
||||
## Basic configuration
|
||||
|
||||
Clone my dotfiles and run the install script
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/ItsDrike/dotfiles ~/dots
|
||||
cd ~/dots
|
||||
./install_root.sh
|
||||
```
|
||||
|
||||
Exit and reenter chroot, this time into zsh shell
|
||||
|
||||
```bash
|
||||
exit
|
||||
arch-chroot /mnt zsh
|
||||
```
|
||||
|
||||
Create non-privileged user
|
||||
|
||||
```bash
|
||||
useradd itsdrike
|
||||
usermod -aG wheel itsdrike
|
||||
install -o itsdrike -g itsdrike -d /home/itsdrike
|
||||
passwd itsdrike
|
||||
chsh -s /usr/bin/zsh itsdrike
|
||||
su -l itsdrike # press q or esc in the default zsh options
|
||||
```
|
||||
|
||||
Setup user account
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/ItsDrike/dotfiles ~/dots
|
||||
cd ~/dots
|
||||
./install_user.sh
|
||||
```
|
||||
|
||||
Exit (logout) the user and relogin, this time into configured zsh shell
|
||||
|
||||
```bash
|
||||
exit
|
||||
su -l itsdrike
|
||||
```
|
||||
|
||||
Install astronvim
|
||||
|
||||
```bash
|
||||
git clone https://github.com/AstroNvim/AstroNvim ~/.config/nvim
|
||||
git clone https://github.com/ItsDrike/AstroNvimUser ~/.config/nvim/lua/user
|
||||
```
|
||||
|
||||
## Auto-mounting encrypted partitions
|
||||
|
||||
We've created a LUKS encrypted partition to store our date into, however it
|
||||
would be very inconvenient to have to mount it ourselves on each boot. Instead,
|
||||
we'll probably want to set up a way to mount them automatically. Leaving only
|
||||
the root partition that we'll need to enter a password for on boot.
|
||||
|
||||
### Key files
|
||||
|
||||
LUKS encryption has support for multiple keys to the same parition. We'll
|
||||
utilize this support and add 2nd key slot to all of the partitions that we wish
|
||||
to auto-mount.
|
||||
|
||||
For this 2nd key slot, we will use a key file, as opposed to the regular
|
||||
user-entered text, so that we can store this key in the file system directly. We
|
||||
will later be using this stored key to auto-mount. The key file will contain
|
||||
random data that will be used as the key.
|
||||
|
||||
Note that it is very important to have these key files themselves stored on an
|
||||
encrypted partition, in this case, we're storing them in /etc/secrets, and our
|
||||
root is encrypted. If you don't have encrypted root partition, it is unsafe to
|
||||
keep those files in there!
|
||||
|
||||
Note that you don't actually need the key files, and if you wish, you can also
|
||||
be prompted to enter a password on each boot instead (for every partition). You
|
||||
should prefer this approach if your root partition isn't encrypted, although
|
||||
know that this can get pretty annoying with more than one encrypted device. If
|
||||
you wish to do this, you can skip this section.
|
||||
|
||||
```bash
|
||||
exit # Go back to root account
|
||||
mkdir -p /etc/secrets
|
||||
dd if=/dev/random bs=4096 count=1 of=/etc/secrets/keyFile-data.bin
|
||||
chmod -R 400 /etc/secrets
|
||||
chmod 700 /etc/secrets
|
||||
```
|
||||
|
||||
The bs argument signifies a block size (in bits), so this will create 4096-bit keys.
|
||||
|
||||
Now we can add this key into our LUKS encrypted data partition:
|
||||
|
||||
```bash
|
||||
cryptsetup luksAddKey /dev/disk/by-label/DATA --new-keyfile /etc/secrets/keyFile-data.bin
|
||||
```
|
||||
|
||||
### /etc/crypttab
|
||||
|
||||
Now that we have the key files ready, we can utilize /etc/crypttab, which
|
||||
is a file that systemd reads during boot (similarly to /etc/fstab), and contains
|
||||
instructions for auto-mounting devices.
|
||||
|
||||
This is the `/etc/crypttab` file that I use:
|
||||
|
||||
<!-- markdownlint-disable MD010 MD013 -->
|
||||
|
||||
```txt
|
||||
# Configuration for encrypted block devices.
|
||||
# See crypttab(5) for details.
|
||||
|
||||
# NOTE: Do not list your root (/) partition here, it must be set up
|
||||
# beforehand by the initramfs (/etc/mkinitcpio.conf).
|
||||
|
||||
# <name> <device> <password> <options>
|
||||
|
||||
cryptdata LABEL=DATA /etc/secrets/keyFile-data.bin discard
|
||||
```
|
||||
|
||||
<!-- markdownlint-enable MD010 MD013 -->
|
||||
|
||||
If you want to be prompted for the password during boot instead of it being read
|
||||
from a file, you can use `none` instead of the file path.
|
||||
|
||||
The `discard` option is specified to enable TRIM on SSDs, which should improve
|
||||
their lifespan. It is not necessary if you're using an HDD.
|
||||
|
||||
### /etc/fstab
|
||||
|
||||
While the crypttab file opens the encrypted block devices and creates the mapper
|
||||
interfaces for them, to mount those to a concrete directory, we still use
|
||||
/etc/fstab. Below is the /etc/fstab that I use on my system:
|
||||
|
||||
<!-- markdownlint-disable MD010 MD013 -->
|
||||
|
||||
```txt
|
||||
# Static information about the filesystems.
|
||||
# See fstab(5) for details.
|
||||
|
||||
# <file system> <dir> <type> <options> <dump> <pass>
|
||||
|
||||
# region: Physical partitions
|
||||
|
||||
# /dev/nvme0n1p2 LABEL=SWAP UUID=d262a2e5-a1a3-42b1-ac83-18639f5e8f3d
|
||||
/dev/disk/by-label/SWAP none swap defaults 0 0
|
||||
|
||||
# /dev/nvme0n1p1 LABEL=EFI UUID=44E8-EB26
|
||||
/dev/disk/by-label/EFI /efi vfat rw,relatime,fmask=0137,dmask=0027,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 2
|
||||
|
||||
# endregion
|
||||
# region: BTRFS subvolumes on /dev/disk/by-label/ARCH (decrypted from ARCH_LUKS)
|
||||
|
||||
# /dev/mapper/cryptroot LABEL=ARCH UUID=bffc7a62-0c7e-4aa9-b10e-fd68bac477e0
|
||||
/dev/mapper/cryptroot / btrfs rw,noatime,compress=zstd:1,ssd,space_cache=v2,subvol=/@ 0 1
|
||||
/dev/mapper/cryptroot /home btrfs rw,noatime,compress=zstd:1,ssd,space_cache=v2,subvol=/@home 0 1
|
||||
/dev/mapper/cryptroot /var/log btrfs rw,noatime,compress=zstd:2,ssd,space_cache=v2,subvol=/@log 0 1
|
||||
/dev/mapper/cryptroot /var/cache btrfs rw,noatime,compress=zstd:3,ssd,space_cache=v2,subvol=/@cache 0 1
|
||||
/dev/mapper/cryptroot /tmp btrfs rw,noatime,compress=no,ssd,space_cache=v2,subvol=/@tmp 0 1
|
||||
/dev/mapper/cryptroot /data btrfs rw,noatime,compress=zstd:5,ssd,space_cache=v2,subvol=/@data 0 2
|
||||
/dev/mapper/cryptroot /.btrfs btrfs rw,noatime,ssd,space_cache=v2 0 2 # btrfs root
|
||||
|
||||
# /dev/mapper/cryptdata LABEL=DATA UUID=...
|
||||
/dev/mapper/cryptdata /data2 btrfs rw,noatime,compress=zstd:5,ssd,space_cache=v2,subvol=/@data 0 2
|
||||
/dev/mapper/cryptdata /backups btrfs rw,noatime,compress=zstd:10,ssd,space_cache=v2,subvol=/@backups 0 2
|
||||
/dev/mapper/cryptdata /.btrfs-data btrfs rw,noatime,ssd,space_cache=v2 0 2 # btrfs root
|
||||
|
||||
# endregion
|
||||
# region: Bind mounts
|
||||
|
||||
# Write kernel images to /efi/arch-1, not directly to efi system partition (esp), to avoid conflicts when dual booting
|
||||
/mnt/efi/arch-1 /boot none rw,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro,bind 0 0
|
||||
|
||||
# endregion
|
||||
```
|
||||
|
||||
<!-- markdownlint-enable MD010 MD013 -->
|
||||
|
||||
## Bootloader
|
||||
|
||||
This guide uses systemd-boot (if you want to use GRUB, just follow the arch wiki).
|
||||
|
||||
### Ask for LUKS password from initramfs
|
||||
|
||||
Ask for encryption password of the root partition in early userspace (only
|
||||
relevant if you're using LUKS encryption), you'll also need to set cryptdevice
|
||||
kernel parameter, specifying the device that should be unlocked here, and the
|
||||
device mapping name. (shown later)
|
||||
|
||||
```bash
|
||||
# Find the line with HOOKS=(...)
|
||||
# Add `keyboard keymap` after `autodetect` (if these hooks are already there,
|
||||
# just keep them, but make sure they're after `autodetect`).
|
||||
# Lastly add `encrypt` before `filesystems`.
|
||||
nvim /etc/mkinitcpio.conf
|
||||
```
|
||||
|
||||
This will configure `mkinitcpio` to build support for the keyboard input, and
|
||||
support for decrypting LUKS devices from within the initial ramdisk
|
||||
environment.
|
||||
|
||||
If you wish, you can also follow the instructions below to auto-enable numlock:
|
||||
|
||||
```bash
|
||||
sudo -u itsdrike yay -S mkinitcpio-numlock
|
||||
# Go to HOOKS and add `numlock` after `keyboard` in:
|
||||
nvim /etc/mkinitcpio.conf
|
||||
```
|
||||
|
||||
Now regenerate the initial ramdisk environment image:
|
||||
|
||||
```bash
|
||||
mkinitcpio -P
|
||||
```
|
||||
|
||||
### Configure systemd-boot
|
||||
|
||||
Install systemd-boot to the EFI system partition (ESP)
|
||||
|
||||
```bash
|
||||
bootctl --esp-path=/efi install
|
||||
# This might report a warning about permissions for the /efi mount point,
|
||||
# these were addressed in the fstab file above (changed fmask and dmask),
|
||||
# if you copied those to your fstab, the permissions will be fixed after reboot
|
||||
```
|
||||
|
||||
Add boot menu entries
|
||||
(Note that we're using LABEL= for cryptdevice, for which `udev` must be before
|
||||
the `encrypt` hook in mkinitcpio `HOOKS`. This should however be the case by default.
|
||||
If you wish, you can also use UUID= or just /dev/XYZ here)
|
||||
|
||||
Create a new file - `/efi/loader/entries/arch-hyprland.conf`, with:
|
||||
|
||||
```bash
|
||||
title Arch Linux (Hyprland)
|
||||
sort-key 0
|
||||
linux /arch-1/vmlinuz-linux
|
||||
initrd /arch-1/amd-ucode.img
|
||||
initrd /arch-1/initramfs-linux.img
|
||||
options cryptdevice=LABEL=ARCH_LUKS:cryptroot:allow-discards
|
||||
options root=/dev/mapper/cryptroot rootflags=subvol=/@
|
||||
options rw loglevel=3
|
||||
```
|
||||
|
||||
And finally configure loader - `/efi/loader/loader.conf` (overwrite the contents):
|
||||
|
||||
```bash
|
||||
default arch-hyprland.conf
|
||||
timeout 4
|
||||
console-mode auto
|
||||
editor yes
|
||||
auto-firmware yes
|
||||
beep no
|
||||
```
|
||||
|
||||
**Reboot**
|
||||
|
||||
```bash
|
||||
exit # go back to live iso (exit chroot)
|
||||
reboot
|
||||
```
|
||||
|
||||
## Post-setup
|
||||
|
||||
Enable Network Time Protocol (time synchronization)
|
||||
|
||||
```bash
|
||||
sudo timedatectl set-ntp true
|
||||
timedatectl status
|
||||
```
|
||||
|
||||
Connect to a wifi network
|
||||
|
||||
```bash
|
||||
nmtui
|
||||
```
|
||||
|
||||
## Footnotes
|
||||
|
||||
Note that this setup is based on my personal system, in which I dual boot
|
||||
multiple (2) arch instances, one running hyprland, the other running KDE (I
|
||||
mainly use the hyprland instance, the KDE one is purely there because it's X11
|
||||
and supports my NVidia card, which Hyprland currenly doesn't).
|
||||
|
||||
The config here only really mentions how to get the first (hyprland)
|
||||
installation ready, however if you wanted to set up both, it's essentially just
|
||||
doing the same thing again, with some minor changes like in the systemd-boot
|
||||
entry and some fstab/crypttab entries.
|
||||
|
||||
I do plan on writing a continuation guide for how to set up the system for GUI
|
||||
(Hyprland) too eventually. Once it's done, I will mention it here.
|
|
@ -1,423 +0,0 @@
|
|||
# Secure boot + TPM unlocking
|
||||
|
||||
This guide assumes you already have a working Arch Linux system, set up by following the `installation.md` guide. That means you have an encrypted root partition, and that your computer has a TPM module.
|
||||
|
||||
This should mean that currently, every time you boot, you have to enter the LUKS password to decrypt your root partition. This can be pretty annoying though, and this guide aims to fix that, without compromising security.
|
||||
|
||||
Once finished, this will basically store the decryption key to your root partition in the TPM module, and so on boot, you'll be able to do so without manually entering your password. This is still perfectly secure, assuming you have a good login screen (in my case, I just use the default linux tty, which I trust fully), and you don't allow anyone to modify the kernel command line (which won't be possible due to secure boot, you'd have to re-sign the images to do so).
|
||||
|
||||
So, if the laptop gets stolen, and the drive is pulled out, it's contents will be LUKS encrypted, so the security here is the same. If the attacker boots up the system on the laptop, they will get past encryption, however they'll only see a login screen, and they'd have to also get past linux authentication to actually get anywhere, making this approach safe enough.
|
||||
|
||||
## Setup Unified Kernel Image (UKI)
|
||||
|
||||
A Unified Kernel Image is a single executable (`.efi` file), which can be booted directly from UEFI firmware, or be
|
||||
automatically sourced by boot loaders with no extra configuration.
|
||||
|
||||
A UKI will include:
|
||||
|
||||
- a UEFI stub loader like (systemd-stub)
|
||||
- the kernel command line
|
||||
- microcode
|
||||
- an initramfs image
|
||||
- a kernel image
|
||||
- a splash screen
|
||||
|
||||
To set up secure boot, this is a requirement, as it's something that can be signed and represents an immutable
|
||||
executable used for booting into your system.
|
||||
|
||||
This is good, because with a standalone bootloader, you would be allowed you to edit the kernel parameters, or even
|
||||
change the kernel image by editing the configuration inside of the (unencrypted) EFI partition. This is obviously
|
||||
dangerous, and we don't want to allow this.
|
||||
|
||||
### Define kernel command line
|
||||
|
||||
Since UKI contains the kernel command line, we will need to define it so that when the image is being built, it can
|
||||
pick it up.
|
||||
|
||||
This is a crucial step especially when you have encryption set up, as without it, the kernel wouldn't know what root
|
||||
partition to use.
|
||||
|
||||
To set this up, we will use `/etc/kernel/cmdline`.
|
||||
|
||||
This is how I setup my kernel arguments (If you're unsure what arguments you need, just check your current
|
||||
systemd-boot configuration, if you followed `installation.md`, you will have it in:
|
||||
`/efi/loader/entries/arch-hyprland.conf`, all of the `options=` line contain kernel command line args):
|
||||
|
||||
```bash
|
||||
echo "rw loglevel=3" > /etc/kernel/cmdline
|
||||
echo "cryptdevice=LABEL=ARCH_LUKS:cryptroot:allow-discards" >> /etc/kernel/cmdline
|
||||
echo "root=/dev/mapper/cryptroot rootflags=subvol=/@" >> /etc/kernel/cmdline
|
||||
```
|
||||
|
||||
Note that you **shouldn't** be specifying the `cryptdevice` or `root` kernel parameters if you're using `systemd`
|
||||
initramfs, rather than `udev` one (you do still need `rootflags` to select the btrfs subvolume though, unless the
|
||||
root partition is your default subvolume). (If you haven't messed with it, you will be using `udev` initramfs).
|
||||
|
||||
### Modify the linux preset for mkinitcpio to build UKIs
|
||||
|
||||
Now open `/etc/mkinitcpio.d/linux.preset`, where you'll want to:
|
||||
|
||||
- Uncomment `ALL_config`
|
||||
- Comment `default_image`
|
||||
- Uncomment `default_uki` (unified kernel image)
|
||||
- Uncomment `default_options`
|
||||
- Comment `fallback_image`
|
||||
- Uncomment `fallback_uki`
|
||||
|
||||
### Recreate /efi
|
||||
|
||||
First, we'll need to unmount `/mnt/boot`, which is currently bind mounted to `/efi/EFI/arch-1`. This is because we'll
|
||||
no longer be storing the kernel, initramfs nor the microcode in the EFI partition at all. The EFI partition will now
|
||||
only contain the UKI, the rest can be left in `/boot`, which will now be a part of the root partition, not mounted
|
||||
anywhere.
|
||||
|
||||
```bash
|
||||
umount /boot
|
||||
vim /etc/fstab # remove the bind mount entry for /boot
|
||||
```
|
||||
|
||||
Now, we will remove everything in the EFI partition, and start from scratch (this will erase the current systemd-boot configuration, you may want to back it up (`/efi/loader/loader.conf` and `/efi/loader/entries/`))
|
||||
|
||||
```bash
|
||||
rm -rf /efi/*
|
||||
```
|
||||
|
||||
Then, we will create the `/efi/EFI/Linux` directory, which will contain our UKIs. (You can change this location in
|
||||
`/etc/mkinitcpio.d/linux.preset` if you wish to use some other directory in the EFI partition, however it is
|
||||
recommended that you stick with Linux).
|
||||
|
||||
```bash
|
||||
mkdir -p /efi/EFI/Linux
|
||||
```
|
||||
|
||||
Finally, we will reinstall the kernel and microcode, populating
|
||||
`/boot` (now on the root partition).
|
||||
|
||||
This will also trigger a initramfs rebuild, which will now create the UKI image based on the `linux.preset` file.
|
||||
|
||||
```bash
|
||||
pacman -S linux amd-ucode
|
||||
```
|
||||
|
||||
### Boot Manager
|
||||
|
||||
This step is optional, because the Unified Kernel Images can actually be booted into directly from the UEFI, if you
|
||||
wish to do that, you can run the following to add them as entries in the UEFI boot menu:
|
||||
|
||||
```bash
|
||||
pacman -S efibootmgr
|
||||
efibootmgr --create --disk /dev/disk/nvme0n1 --part 1 --label "Arch Linux (Hyprland)" --loader 'EFI\Linux\arch-linux.efi' --unicode
|
||||
efibootmgr -c -d /dev/disk/nvme0n1 -p 1 -L "Arch Linux (Hyprland) Fallback" -l 'EFI\Linux\arch-linux-fallback.efi' -u
|
||||
pacman -R systemd-boot
|
||||
```
|
||||
|
||||
You can also specify additional kernel parameters / override the default ones in the UKI, by simply adding a string as
|
||||
a last positional argument to the `efibootmgr` command, allowing you to create entires with different kernel command
|
||||
lines easily.
|
||||
|
||||
Doing the above is technically safer than going with a boot manager, as it cuts out the middle-man entirely, however it
|
||||
can sometimes be nice to have boot manager, as it can show you a nice boot menu, and allow you to modify the kernel
|
||||
parameters, or add entries for different operating systems very easily, without having to rely on the specific
|
||||
implementation of the boot menu in your UEFI firmware (which might take really long to open, or just generally not
|
||||
provide that good/clean experience). Because of that, I like to instead still install the `systemd-boot`. To do so, we can
|
||||
just install normally with:
|
||||
|
||||
```bash
|
||||
bootctl install --esp-path=/efi
|
||||
```
|
||||
|
||||
We can now reboot. Systemd-boot will pick up any UKI images in `/efi/EFI/Linux` automatically (this path is
|
||||
hard-coded), even without any entry configurations.
|
||||
|
||||
That said, if you do wish to do so, you can still add an explicit entry for your configuration in
|
||||
`/efi/loader/entries/arch-hyprland.conf`:
|
||||
|
||||
```
|
||||
title Arch Linux (Hyprland)
|
||||
sort-key 0
|
||||
efi /EFI/Linux/arch-linux.efi
|
||||
# If you wish, you can also specify kernel options here, it will
|
||||
# append/override those in the UKI image
|
||||
#options rootflags=subvol=/@
|
||||
#options rw loglevel=3
|
||||
```
|
||||
|
||||
Although do note that if your UKI image is stored in `/efi/EFI/Linux`, because systemd-boot picks it up automatically,
|
||||
you will see the entry twice, so you'll likely want to change the target directory for the UKIs (in
|
||||
`/etc/mkinitcpio.d/linux.preset`) to something else.
|
||||
|
||||
I however wouldn't recommend this approach, and I instead just let systemd-boot autodetect the images, unless you need
|
||||
something specific.
|
||||
|
||||
If everything went well, you should see a new systemd based initramfs, from where you'll be prompted for the LUKS2
|
||||
password.
|
||||
|
||||
## Secure Boot
|
||||
|
||||
Now that we're booting with UKIs, we have images that that we'll be able to sign for secure boot, hence only allowing
|
||||
us to boot from those images.
|
||||
|
||||
However before we can set signing up, we will need to create new signing keys, and upload them into secure boot.
|
||||
|
||||
### Enter Setup mode
|
||||
|
||||
To allow us to upload new signing keys into secure boot, we will need to enter "setup mode". This should be possible
|
||||
by going to the Secure Boot category in your UEFI settings, and clicking on Delete/Clear certificates, or there could
|
||||
even just be a "Setup Mode" option directly.
|
||||
|
||||
Once enabled, save the changes and boot back into Arch linux.
|
||||
|
||||
```bash
|
||||
pacman -S sbctl
|
||||
sbctl status
|
||||
```
|
||||
|
||||
Make sure that `sbctl` reports that Setup Mode is Enabled.
|
||||
|
||||
### Create Secure Boot keys
|
||||
|
||||
We can now create our new signing keys for secure boot. These keys will be stored in `/usr/share/secureboot` (so in
|
||||
our encrypted root partition). Once created, we will add (enroll) these keys into the UEFI firmware (only possible
|
||||
when in setup mode)
|
||||
|
||||
```bash
|
||||
sbctl create-keys
|
||||
# the -m adds microsoft vendor key, required for most HW. Not using it could brick your device.
|
||||
sbctl enroll-keys -m
|
||||
```
|
||||
|
||||
Note: If you see messages about immutable files, run `chattr -i [file]` for all of the listed immutable files, then
|
||||
re-run enroll-keys command. (Linux kernel will sometimes mark the runtime EFI files as immutable for security - to
|
||||
prevent bricking the device with just `rm -rf /*`, or similar stupid commands, however since we trust that `sbctl`
|
||||
will work and won't do anything malicious, we can just remove the immutable flag, and re-running will now work).
|
||||
|
||||
### Sign the bootloader and Unified Kernel Images
|
||||
|
||||
Finally then, we can sign the `.efi` executables that we'd like to use:
|
||||
|
||||
```bash
|
||||
sbctl sign -s -o /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed /usr/lib/systemd/boot/efi/systemd-bootx64.efi
|
||||
sbctl sign -s /efi/EFI/BOOT/BOOTX64.EFI
|
||||
sbctl sign -s /efi/EFI/systemd/systemd-bootx64.efi
|
||||
sbctl sign -s /efi/EFI/Linux/arch-linux.efi
|
||||
sbctl sign -s /efi/EFI/Linux/arch-linux-fallback.efi
|
||||
```
|
||||
|
||||
(If you're not using `systemd-boot`, only sign the UKI images in `/efi/EFI/Linux`)
|
||||
|
||||
The `-s` flag means save: The files will be automatically re-signed when we update the kernel (via a sbctl pacman
|
||||
hook). To make sure that this is the case, we can run `pacman -S linux` and check that messages about image
|
||||
signing appear.
|
||||
|
||||
When done, we can make sure that everything that needed to be signed really was signed with:
|
||||
|
||||
```bash
|
||||
sbctl verify
|
||||
```
|
||||
|
||||
### Reboot and enable secure boot
|
||||
|
||||
We should now be ready to enable secure boot, as our .efi images were signed, and the signing key was uploaded.
|
||||
|
||||
```bash
|
||||
sbctl status
|
||||
```
|
||||
|
||||
If you see Secure Boot marked as Enabled, it worked!
|
||||
|
||||
## Set up TPM unlocking
|
||||
|
||||
We'll now set up the TPM module to store a LUKS encryption key for our root partition, which it can release if certain
|
||||
conditions are met (I'll talk about the specific conditions a few sections later). This will allow us to set it up in
|
||||
such a way, that allows automatic unlocking without having to enter the password at boot.
|
||||
|
||||
This is safe, because set up correctly, TPM will only release the password to unlock the drive if there wasn't any
|
||||
editing done to the way the system was booted up, in which case we should always end up at a lockscreen after the
|
||||
bootup, which will be our line of defense against attackers, rather than it being the encryption password itself.
|
||||
|
||||
Do make sure that if you go this route, your lockscreen doesn't have any vulnerabilities and can't be easily bypassed.
|
||||
In my case, I'm using the default linux account login screen, which I do trust is safe enough to keep others without
|
||||
password out. I also have PAM set up in such a way that after 3 failed attempts, the account will get locked for 10
|
||||
minutes, which should prevent any brute-force attempts (this is actually the default).
|
||||
|
||||
Since TPM is a module integrated in the CPU or the motherboard, so if someone took out the physical drive with the
|
||||
encrypted data, they would still need to have a LUKS decryption key to actually be able to read the contents of the
|
||||
root partition.
|
||||
|
||||
### Make sure you have a TPM v2 module
|
||||
|
||||
```bash
|
||||
pacman -S tpm2-tss tpm2-tools
|
||||
```
|
||||
|
||||
Verify that your system does actually have a TPM v2 module
|
||||
|
||||
```bash
|
||||
systemd-cryptenroll --tpm2-device=list
|
||||
```
|
||||
|
||||
Make sure that there is a device listed.
|
||||
|
||||
### Switch from udev initramfs to systemd
|
||||
|
||||
By default, your initramfs will be using `udev`, however you can instead use `systemd`, which has a bunch of extra
|
||||
capabilities, such as being able to pick up the key from TPM2 chip.
|
||||
|
||||
Open `/etc/mkinitcpio.conf` and find a line that starts with `HOOKS=`
|
||||
|
||||
- Change `udev` to `systemd`
|
||||
- Change `keymap consolefont` to `sd-vconsole`
|
||||
- Add `sd-encrypt` before `block`, and remove `encrypt`
|
||||
- If you were using `mkinitcpio-numlock`, also remove `numlock`, it doesn't work with systemd
|
||||
|
||||
(As an alternative to `mkinitcpio-numlock`, there is `systemd-numlockontty`, which creates a systemd service that
|
||||
enables numlock in TTYs after booting (you'll need to enable it), this however doesn't happen in initramfs directly,
|
||||
only aftwerwars. This shouldn't be too annoying though, as we'lll no longer have to be entering the encryption
|
||||
password, which is the only reason we'd need numlock in initramfs anyway.)
|
||||
|
||||
Additionally, with systemd initramfs, you shouldn't be specifying `root` nor `cryptdevice` kernel arguments, as systemd
|
||||
can actually pick those up automatically (they'll be discovered by
|
||||
[systemd-cryptsetup-generator](https://wiki.archlinux.org/title/Dm-crypt/System_configuration#Using_systemd-cryptsetup-generator)
|
||||
and auto-mounted from initramfs via
|
||||
[systemd-gpt-auto-generator](https://wiki.archlinux.org/title/Systemd#GPT_partition_automounting)). We will however
|
||||
still need the `rootflags` argument for selecting the btrfs subvolume (unless your default subvolume is the root
|
||||
partition subvolume).
|
||||
|
||||
So, let's edit our kernel parameters:
|
||||
|
||||
```bash
|
||||
echo "rw loglevel=3" > /etc/kernel/cmdline # overwrite the existing cmdline
|
||||
echo "rootflags=subvol=/@" >> /etc/kernel/cmdline
|
||||
```
|
||||
|
||||
You'll also need to modify the `/etc/fstab`, as systemd will not use the `/dev/mapper/cryptroot` name, but rather
|
||||
you'll have a `/dev/gpt-auto-root` (there'll also be `/dev/gpt-auto-root-luks`, which is the encrypted partition). If
|
||||
you absolutely insist on using a mapper device, you can also use `/dev/mapper/root` though, which is what systemd
|
||||
will actually call it.
|
||||
|
||||
```bash
|
||||
vim /etc/fstab
|
||||
```
|
||||
|
||||
We can now regenerate the initramfs with: `pacman -S linux` (we could also do `mkinitcpio -P`, however that won't
|
||||
trigger the pacman hook which auto-signs our final UKI images, so we'd have to re-sign them with `sbctl` manually)
|
||||
and reboot to check if it worked.
|
||||
|
||||
### Choosing PCRs
|
||||
|
||||
PCR stands for Platform Configuration Register, and all TPM v2 modules have a bunch of these registers, which hold
|
||||
hashes about the system's state. These registers are read-only, and their value is set by the TPM module itself.
|
||||
|
||||
The data held by the TPM module (our LUKS encryption key) can then only be accessed when all of the selected PCR
|
||||
registers contain the expected values. You can find a list of the PCR registers on [Arch
|
||||
Wiki](https://wiki.archlinux.org/title/Trusted_Platform_Module#Accessing_PCR_registers).
|
||||
|
||||
You can look at the current values of these registers with this command:
|
||||
|
||||
```bash
|
||||
systemd-analyze pcrs
|
||||
```
|
||||
|
||||
For our purposes, we will choose these:
|
||||
|
||||
- **PCR0**: Hash of the UEFI firmware executable code (may change if you update UEFI)
|
||||
- **PCR7**: Secure boot state - contains the certificates used to validate each boot application
|
||||
- **PCR12**: Overridden kernel command line, credentials
|
||||
|
||||
> [!IMPORTANT]
|
||||
> If you're using systemd-boot (instead of booting directly from the UKI images), it is very important that we choose
|
||||
> all 3, including PCR12, as many tutorials only recommend 0 and 7, which would however lead to a security hole, where
|
||||
> an attacker would be able to remove the drive with the (unencrypted) EFI partition, and modify the systemd-boot
|
||||
> loader config (`loaders/loader.conf`), adding `editor=yes`, and the put the drive back in.
|
||||
>
|
||||
> This wouldn't violate secure boot, as the `.efi` image files were unchanged, and are still signed, so the attacker
|
||||
> would be able to boot into the systemd-boot menu, from where they could edit the boot entry for our UKI and modify
|
||||
> the kernel parameters (yes, even though UKIs contain the kernel command line inside of them, systemd-boot can still
|
||||
> edit those arguments if `editor=yes`).
|
||||
>
|
||||
> From there, the attacker could simply add a kernel argument like `init=/bin/bash`, which would bypass systemd as the
|
||||
> init system and instead make the kernel run bash executable as the PID=1 (init) program. This would mean you would
|
||||
> get directly into bash console that is running as root, without any need to enter a password.
|
||||
>
|
||||
> However, with PCR12, this is prevented, as it detects that the kernel cmdline was overridden, and so the TPM module
|
||||
> wouldn't release the key.
|
||||
|
||||
The nice thing about also selecting PCR12 is that it will even allow us to securely keep `editor=yes` in our
|
||||
`loader.conf`, for easy debugging, as all that will happen if we do edit the kernel command line will be that the TPM
|
||||
module will not release the credentials, and so the initramfs will just ask us to enter the password manually.
|
||||
|
||||
### Generate recovery key
|
||||
|
||||
The following command will generate a new LUKS key and automatically add it to the encrypted root. You will be prompted
|
||||
for a LUKS password to this device.
|
||||
|
||||
This step is optional, as all it does is adding another LUKS keyslot with a generated recovery key, so that in case TPM
|
||||
wouldn't unlock the drive, you can use this key instead.
|
||||
|
||||
You're expected to delete your own key, which is assumed to be less secure than
|
||||
what this will generate. We will do this after the next step.
|
||||
|
||||
If you instead wish to keep your own key working, feel free to skip this step, and the key removal step later.
|
||||
|
||||
```bash
|
||||
systemd-cryptenroll /dev/gpt-auto-root-luks --recovery-key
|
||||
```
|
||||
|
||||
### Enroll the key into TPM
|
||||
|
||||
The following command will enroll a new key into the TPM module and add it as a new keyslot of the specified LUKS2 encrypted device.
|
||||
|
||||
We also specify `--tpm2-pcrs=0+7+12`, which selects the PCR registers that we decided on above.
|
||||
|
||||
Note: If you already had something in the tpm2 moudle, you will want to add `--wipe-slot=tpm2` too.
|
||||
|
||||
You will be prompted for a LUKS password to this device (you can still enter your original key, you don't need to use
|
||||
the recovery one, as we haven't deleted the original one yet).
|
||||
|
||||
```bash
|
||||
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7+12 /dev/gpt-auto-root-luks
|
||||
```
|
||||
|
||||
This will enroll the TPM2 token token as a key slot 2 for the encrypted drive.
|
||||
|
||||
If you're extra paranoid, you can also provide `--tpm2-with-pin=yes`, to prompt for a PIN code on each boot.
|
||||
|
||||
To check that it worked, you can use:
|
||||
|
||||
```bash
|
||||
cryptsetup luksDump /dev/gpt-auto-root-luks
|
||||
```
|
||||
|
||||
Make sure that there is an additional LUKS key slot.
|
||||
|
||||
### Remove original key
|
||||
|
||||
This is an optional step, only follow it if you have generated and properly stored a recovery key.
|
||||
|
||||
**Warning:** Make absolutely certain that the recovery key does in fact work before doing this, otherwise, you may get
|
||||
locked out! You can test your recovery key with:
|
||||
|
||||
```bash
|
||||
cryptsetup luksOpen /dev/gpt-auto-root-luks crypttemp # enter the recovery key
|
||||
cryptsetup luksClose crypttemp
|
||||
```
|
||||
|
||||
If this worked, proceed to:
|
||||
|
||||
```bash
|
||||
cryptsetup luksRemoveKey /dev/disk/by-label/ARCH_LUKS # Enter your key to be deleted
|
||||
```
|
||||
|
||||
### Reboot
|
||||
|
||||
After a reboot, the system should now get unlocked automatically without prompting for the password.
|
||||
|
||||
### Remove key from TPM
|
||||
|
||||
In case you'd ever want to remove the LUKS key from TPM, you can do so simply with:
|
||||
|
||||
```bash
|
||||
csystemd-cryptenroll --wipe-slot=tpm2
|
||||
```
|
||||
|
||||
This will actually also remove the LUKS key from the `/dev/gpt-auto-root-luks` device.
|
3
home/.config/Kvantum/kvantum.kvconfig
Normal file
3
home/.config/Kvantum/kvantum.kvconfig
Normal file
|
@ -0,0 +1,3 @@
|
|||
[General]
|
||||
theme=catppuccin-mocha-blue
|
||||
|
|
@ -5,16 +5,17 @@
|
|||
# Which monitor should the notifications be shown on
|
||||
monitor = 0
|
||||
|
||||
# Display notifications on focused monitor. Possible modes:
|
||||
# mouse: follow mouse pointer
|
||||
# keyboard: follow window with keyboard focus
|
||||
# none: don't follow anything
|
||||
# Display notification on focused monitor. Possible modes are:
|
||||
# mouse: follow mouse pointer
|
||||
# keyboard: follow window with keyboard focus
|
||||
# none: don't follow anything
|
||||
#
|
||||
# keyboard needs a window manager that exports
|
||||
# _NET_ACTIVE_WINDOW propery! This should be the case for almost
|
||||
# all modern window managers.
|
||||
# "keyboard" needs a window manager that exports the
|
||||
# _NET_ACTIVE_WINDOW property.
|
||||
# This should be the case for almost all modern window managers.
|
||||
#
|
||||
# If this option isn't none, monitor option will be ignored.
|
||||
# If this option is set to mouse or keyboard, the monitor option
|
||||
# will be ignored.
|
||||
follow = mouse
|
||||
|
||||
### Geometry ###
|
||||
|
@ -38,7 +39,7 @@
|
|||
scale = 0
|
||||
|
||||
# Maximum number of notifications (0 means no limit)
|
||||
notification_limit = 0
|
||||
notification_limit = 10
|
||||
|
||||
### Progress bar ###
|
||||
|
||||
|
@ -59,6 +60,20 @@
|
|||
# Set the maximum width for the progress bar
|
||||
progress_bar_max_width = 300
|
||||
|
||||
# Corner radius for the progress bar. 0 disables rounded corners.
|
||||
progress_bar_corner_radius = 0
|
||||
|
||||
# Define which corners to round when drawing the progress bar. If progress_bar_corner_radius
|
||||
# is set to 0 this option will be ignored.
|
||||
progress_bar_corners = all
|
||||
|
||||
# Corner radius for the icon image.
|
||||
icon_corner_radius = 0
|
||||
|
||||
# Define which corners to round when drawing the icon image. If icon_corner_radius
|
||||
# is set to 0 this option will be ignored.
|
||||
icon_corners = all
|
||||
|
||||
# Show how many messages are currently hidden (because of
|
||||
# notification_limit).
|
||||
indicate_hidden = yes
|
||||
|
@ -69,7 +84,9 @@
|
|||
transparency = 20
|
||||
|
||||
# Draw a line of "separator_height" pixel height between two
|
||||
# notifications. Set to 0 to disable.
|
||||
# notifications.
|
||||
# Set to 0 to disable.
|
||||
# If gap_size is greater than 0, this setting will be ignored.
|
||||
separator_height = 2
|
||||
|
||||
# Padding between text and separator.
|
||||
|
@ -86,7 +103,13 @@
|
|||
frame_width = 3
|
||||
|
||||
# Defines color of the frame around the notification window
|
||||
frame_color = "#aaaaaa"
|
||||
frame_color = "#27292c";
|
||||
|
||||
# Size of gap to display between notifications - requires a compositor.
|
||||
# If value is greater than 0, separator_height will be ignored and a border
|
||||
# of size frame_width will be drawn around each notification instead.
|
||||
# Click events on gaps do not currently propagate to applications below.
|
||||
gap_size = 0
|
||||
|
||||
# Define a color for the separator.
|
||||
# possible values are:
|
||||
|
@ -96,19 +119,26 @@
|
|||
# * anything else will be interpreted as a X color.
|
||||
separator_color = frame
|
||||
|
||||
# Sort messages by urgency.
|
||||
# Sort type.
|
||||
# possible values are:
|
||||
# * id: sort by id
|
||||
# * urgency_ascending: sort by urgency (low then normal then critical)
|
||||
# * urgency_descending: sort by urgency (critical then normal then low)
|
||||
# * update: sort by update (most recent always at the top)
|
||||
sort = yes
|
||||
|
||||
# Don't remove messages if the user is idle (no mouse/keyboard input)
|
||||
# for longer than idle_threshold seconds (0 to disable)
|
||||
# Don't remove messages, if the user is idle (no mouse or keyboard input)
|
||||
# for longer than idle_threshold seconds.
|
||||
# Set to 0 to disable.
|
||||
# A client can set the 'transient' hint to bypass this. See the rules
|
||||
# section for how to disable this if necessary
|
||||
idle_threshold = 120
|
||||
|
||||
### Text ###
|
||||
|
||||
font = JetBrains Mono 11
|
||||
|
||||
# The spacing between the lines. If the height is smaller than the
|
||||
# The spacing between lines. If the height is smaller than the
|
||||
# font height, it will get raised to the font height.
|
||||
line_height = 0
|
||||
|
||||
|
@ -120,7 +150,7 @@
|
|||
# <u>underline</u>
|
||||
#
|
||||
# For a complete reference see
|
||||
# <http://developer.gnome.org/pango/stable/PangoMarkupFormat.html>.
|
||||
# <https://docs.gtk.org/Pango/pango_markup.html>.
|
||||
#
|
||||
# strip: This setting is provided for compatibility with some broken
|
||||
# clients that send markup even though it's not enabled on the
|
||||
|
@ -160,17 +190,18 @@
|
|||
# of the noticication. If set to no, longer sententences will be truncated
|
||||
word_wrap = yes
|
||||
|
||||
# Specify where to make an ellipsis in the long lines.
|
||||
# Possible values are "start", "middle", "end".
|
||||
# Show age of message if message is older than show_age_threshold
|
||||
# seconds.
|
||||
# Set to -1 to disable.
|
||||
show_age_threshold = 60
|
||||
|
||||
# Specify where to make an ellipsis in long lines.
|
||||
# Possible values are "start", "middle" and "end".
|
||||
ellipsize = middle
|
||||
|
||||
# Ignore newlines '\n' in notifications.
|
||||
ignore_newline = no
|
||||
|
||||
# Show age of message if message is older than show_age_threshold seconds
|
||||
# Set to -1 to disable, 0 to always show.
|
||||
show_age_threshold = 60
|
||||
|
||||
# Merge multiple notifications with the same content
|
||||
stack_duplicates = true
|
||||
|
||||
|
@ -182,6 +213,15 @@
|
|||
|
||||
### Icons ###
|
||||
|
||||
# Recursive icon lookup. You can set a single theme, instead of having to
|
||||
# define all lookup paths.
|
||||
enable_recursive_icon_lookup = true
|
||||
|
||||
# Set icon theme (only used for recursive icon lookup)
|
||||
# You can also set multiple icon themes, with the leftmost one being used first.
|
||||
# icon_theme = "Adwaita, breeze"
|
||||
icon_theme = Papirus-Dark, Adwaita
|
||||
|
||||
# Align icons left/right/off
|
||||
icon_position = left
|
||||
|
||||
|
@ -193,8 +233,8 @@
|
|||
# Scale larger icons down to this size, set to 0 to disable
|
||||
max_icon_size = 32
|
||||
|
||||
# Paths to default icons
|
||||
icon_path = /usr/share/icons/hicolor/16x16/status/:/usr/share/icons/hicolor/16x16/devices/:/usr/share/icons/hicolor/16x16/apps/
|
||||
# Paths to default icons (only necessary when not using recursive icon lookup)
|
||||
#icon_path = /usr/share/icons/hicolor/16x16/status/:/usr/share/icons/hicolor/16x16/devices/:/usr/share/icons/hicolor/16x16/apps/
|
||||
|
||||
### History ###
|
||||
|
||||
|
@ -229,6 +269,13 @@
|
|||
# notification height to avoid clipping text and/or icons.
|
||||
corner_radius = 0
|
||||
|
||||
# Define which corners to round when drawing the window. If the corner radius
|
||||
# is set to 0 this option will be ignored.
|
||||
#
|
||||
# Comma-separated list of the corners. The accepted corner values are bottom-right,
|
||||
# bottom-left, top-right, top-left, top, bottom, left, right or all.
|
||||
corners = all
|
||||
|
||||
# Ignore the dbus closeNotification message.
|
||||
# Useful to enforce the timeout set by dunst configuration. Without this
|
||||
# parameter, an application may close the notification sent before the
|
||||
|
@ -293,8 +340,9 @@
|
|||
foreground = "#ffffff"
|
||||
|
||||
timeout = 5
|
||||
|
||||
# Icon for notifications with low urgency, uncomment to enable
|
||||
#icon = /path/to/icon
|
||||
#default_icon = /path/to/icon
|
||||
|
||||
[urgency_normal]
|
||||
highlight = "#fe6c5a"
|
||||
|
@ -303,8 +351,9 @@
|
|||
foreground = "#ffffffff"
|
||||
|
||||
timeout = 10
|
||||
|
||||
# Icon for notifications with normal urgency, uncomment to enable
|
||||
#icon = /path/to/icon
|
||||
#default_icon = /path/to/icon
|
||||
|
||||
[urgency_critical]
|
||||
highlight = "#fe6c5a"
|
||||
|
@ -313,7 +362,10 @@
|
|||
foreground = "#ffffffff"
|
||||
|
||||
timeout = 0
|
||||
override_pause_level = 60
|
||||
|
||||
icon = arbt
|
||||
|
||||
# Icon for notifications with critical urgency, uncomment to enable
|
||||
#icon = /path/to/icon
|
||||
|
||||
|
@ -352,6 +404,7 @@
|
|||
# ellipsize
|
||||
# alignment
|
||||
# hide_text
|
||||
# override_pause_level
|
||||
#
|
||||
# Shell-like globbing will get expanded.
|
||||
#
|
||||
|
@ -359,6 +412,10 @@
|
|||
# GLib based applications export their desktop-entry name. In comparison to the appname,
|
||||
# the desktop-entry won't get localized.
|
||||
#
|
||||
# You can also allow a notification to appear even when paused. Notification will appear whenever notification's override_pause_level >= dunst's paused level.
|
||||
# This can be used to set partial pause modes, where more urgent notifications get through, but less urgent stay paused. To do that, you can override the following in the rules:
|
||||
# override_pause_level = X
|
||||
|
||||
# SCRIPTING
|
||||
# You can specify a script that gets run when the rule matches by
|
||||
# setting the "script" option.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.window_name {
|
||||
font-family: "JetBrains Mono", "Font Awesome 6 Free", sans-serif;
|
||||
font-family: "Monaspace Krypton";
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
|
|
@ -2,13 +2,14 @@
|
|||
background-color: $bg1-a;
|
||||
border-radius: 25px;
|
||||
|
||||
.icon, .icon label {
|
||||
font-family: "Material Symbols Outlined";
|
||||
font-size: 1.15rem;
|
||||
.icon,
|
||||
.icon label {
|
||||
font-family: "JetBrainsMono Nerd Font", "Material Symbols Outlined";
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.value {
|
||||
margin: 0 9px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.focused {
|
||||
|
|
|
@ -34,13 +34,13 @@
|
|||
background-color: $bg-a;
|
||||
color: $fg;
|
||||
|
||||
font-family: "JetBrains Mono", "Jost *", sans-serif;
|
||||
font-family: "JetBrains Mono";
|
||||
|
||||
label {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
// TODO: Use ercentages (for some reason it fails now)
|
||||
// TODO: Use percentages (for some reason it fails now)
|
||||
min-width: 1900px;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
(defvar terminal "alacritty -e")
|
||||
(defvar terminal "kitty -e")
|
||||
|
||||
(include "./modules/variables.yuck")
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
(defwidget bitcoin_module []
|
||||
(eventbox
|
||||
:onclick "~/.local/bin/scripts/cli/bitcoin | xargs -I_ ${EWW_CMD} update bitcoin=_"
|
||||
:onclick "bitcoin | xargs -I{} ${EWW_CMD} update bitcoin={}"
|
||||
:class "module bitcoin"
|
||||
|
||||
(box
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
(defwidget clock_module []
|
||||
|
||||
(eventbox
|
||||
:onclick "${EWW_CMD} open --toggle calendar"
|
||||
:tooltip {time.day}
|
||||
:class "module clock"
|
||||
:onclick "${EWW_CMD} open --toggle calendar"
|
||||
|
||||
(box
|
||||
:space-evenly false
|
||||
|
@ -13,5 +13,6 @@
|
|||
:text "")
|
||||
(label
|
||||
:class "value"
|
||||
:text "${time.date} ${time.hour}:${time.minute}"))
|
||||
))
|
||||
:text "${time.date} ${time.hour}:${time.minute}")
|
||||
)))
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
(defpoll bitcoin
|
||||
:interval "5m"
|
||||
:initial "$N/A"
|
||||
`~/.local/bin/scripts/cli/bitcoin`)
|
||||
`bitcoin`)
|
||||
|
||||
; TODO: Figure out how to store this one-time
|
||||
(defpoll kernel
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# shellcheck source=include
|
||||
source "./scripts/include"
|
||||
|
|
|
@ -1,83 +1,82 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [ "$1" = "temperature" ]; then
|
||||
watch_cmd="{t}"
|
||||
update_cmd="UpdateTemperature"
|
||||
update_signature="n"
|
||||
set_cmd="Temperature"
|
||||
set_signature="q"
|
||||
default_val=6500
|
||||
click_val=4500
|
||||
scroll_change=100
|
||||
cmp_op="<"
|
||||
watch_cmd="{t}"
|
||||
update_cmd="UpdateTemperature"
|
||||
update_signature="n"
|
||||
set_cmd="Temperature"
|
||||
set_signature="q"
|
||||
default_val=6500
|
||||
click_val=4500
|
||||
scroll_change=100
|
||||
cmp_op="<"
|
||||
|
||||
elif [ "$1" = "brightness" ]; then
|
||||
watch_cmd="{bp}"
|
||||
update_cmd="UpdateBrightness"
|
||||
update_signature="d"
|
||||
set_cmd="Brightness"
|
||||
set_signature="d"
|
||||
default_val=1
|
||||
click_val=0.8
|
||||
scroll_change=0.02
|
||||
cmp_op="<"
|
||||
watch_cmd="{bp}"
|
||||
update_cmd="UpdateBrightness"
|
||||
update_signature="d"
|
||||
set_cmd="Brightness"
|
||||
set_signature="d"
|
||||
default_val=1
|
||||
click_val=0.8
|
||||
scroll_change=0.02
|
||||
cmp_op="<"
|
||||
|
||||
elif [ "$1" = "gamma" ]; then
|
||||
watch_cmd="{g}"
|
||||
update_cmd="UpdateGamma"
|
||||
update_signature="d"
|
||||
set_cmd="Gamma"
|
||||
set_signature="d"
|
||||
default_val=1
|
||||
click_val=1.1
|
||||
scroll_change=0.02
|
||||
cmp_op=">"
|
||||
watch_cmd="{g}"
|
||||
update_cmd="UpdateGamma"
|
||||
update_signature="d"
|
||||
set_cmd="Gamma"
|
||||
set_signature="d"
|
||||
default_val=1
|
||||
click_val=1.1
|
||||
scroll_change=0.02
|
||||
cmp_op=">"
|
||||
|
||||
else
|
||||
>&2 echo "Invalid option, first argument must be one of: temperature, brightness, gamma"
|
||||
exit 1
|
||||
>&2 echo "Invalid option, first argument must be one of: temperature, brightness, gamma"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
if [ "$2" = "watch" ]; then
|
||||
exec wl-gammarelay-rs watch "$watch_cmd"
|
||||
exec wl-gammarelay-rs watch "$watch_cmd"
|
||||
|
||||
elif [ "$2" = "get" ]; then
|
||||
exec busctl --user get-property rs.wl-gammarelay / rs.wl.gammarelay "$set_cmd" | cut -d' ' -f2
|
||||
exec busctl --user get-property rs.wl-gammarelay / rs.wl.gammarelay "$set_cmd" | cut -d' ' -f2
|
||||
|
||||
elif [ "$2" = "scroll" ]; then
|
||||
if [ "$3" = "up" ]; then
|
||||
sign="+"
|
||||
elif [ "$3" = "down" ]; then
|
||||
sign="-"
|
||||
else
|
||||
>&2 echo "Invalid sign, second argument must be one of: up, down"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$3" = "up" ]; then
|
||||
sign="+"
|
||||
elif [ "$3" = "down" ]; then
|
||||
sign="-"
|
||||
else
|
||||
>&2 echo "Invalid sign, second argument must be one of: up, down"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exec busctl --user -- call rs.wl-gammarelay / rs.wl.gammarelay "$update_cmd" "$update_signature" ${sign}${scroll_change}
|
||||
exec busctl --user -- call rs.wl-gammarelay / rs.wl.gammarelay "$update_cmd" "$update_signature" ${sign}${scroll_change}
|
||||
|
||||
elif [ "$2" = "set" ]; then
|
||||
mode="$3"
|
||||
if [ "$mode" = "toggle" ]; then
|
||||
cur_val="$(busctl --user get-property rs.wl-gammarelay / rs.wl.gammarelay "$set_cmd" | cut -d' ' -f2)"
|
||||
if [ "$(echo "$cur_val $cmp_op $default_val" | bc -l)" = "1" ]; then
|
||||
mode="off"
|
||||
else
|
||||
mode="on"
|
||||
fi
|
||||
fi
|
||||
mode="$3"
|
||||
if [ "$mode" = "toggle" ]; then
|
||||
cur_val="$(busctl --user get-property rs.wl-gammarelay / rs.wl.gammarelay "$set_cmd" | cut -d' ' -f2)"
|
||||
if [ "$(echo "$cur_val $cmp_op $default_val" | bc -l)" = "1" ]; then
|
||||
mode="off"
|
||||
else
|
||||
mode="on"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$mode" = "on" ]; then
|
||||
exec busctl --user -- set-property rs.wl-gammarelay / rs.wl.gammarelay "$set_cmd" "$set_signature" "$click_val"
|
||||
elif [ "$mode" = "off" ]; then
|
||||
exec busctl --user -- set-property rs.wl-gammarelay / rs.wl.gammarelay "$set_cmd" "$set_signature" "$default_val"
|
||||
else
|
||||
>&2 echo "Invalid mode, third argument, must be one of: toggle, on, off"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$mode" = "on" ]; then
|
||||
exec busctl --user -- set-property rs.wl-gammarelay / rs.wl.gammarelay "$set_cmd" "$set_signature" "$click_val"
|
||||
elif [ "$mode" = "off" ]; then
|
||||
exec busctl --user -- set-property rs.wl-gammarelay / rs.wl.gammarelay "$set_cmd" "$set_signature" "$default_val"
|
||||
else
|
||||
>&2 echo "Invalid mode, third argument, must be one of: toggle, on, off"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
else
|
||||
>&2 echo "Invalid operation, second argument must be one of: watch, scroll, set"
|
||||
exit 1
|
||||
>&2 echo "Invalid operation, second argument must be one of: watch, scroll, set"
|
||||
exit 1
|
||||
fi
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# $1: Current number
|
||||
# $2: Range minimum
|
||||
# $3: Range maximum
|
||||
# $4-: Icons as individual arguments
|
||||
pick_icon() {
|
||||
cur="$1"
|
||||
min="$2"
|
||||
max="$3"
|
||||
shift 3
|
||||
icons=( "$@" )
|
||||
cur="$1"
|
||||
min="$2"
|
||||
max="$3"
|
||||
shift 3
|
||||
icons=("$@")
|
||||
|
||||
index="$(echo "($cur-$min)/(($max-$min)/${#icons[@]})" | bc)"
|
||||
index="$(echo "($cur-$min)/(($max-$min)/${#icons[@]})" | bc)"
|
||||
|
||||
# Print the picked icon, handling overflows/underflows, i.e. if our index is <0 or >len(icons)
|
||||
if [ "$index" -ge "${#icons[@]}" ]; then
|
||||
index=-1
|
||||
elif [ "$index" -lt 0 ]; then
|
||||
index=0
|
||||
fi
|
||||
# Print the picked icon, handling overflows/underflows, i.e. if our index is <0 or >len(icons)
|
||||
if [ "$index" -ge "${#icons[@]}" ]; then
|
||||
index=-1
|
||||
elif [ "$index" -lt 0 ]; then
|
||||
index=0
|
||||
fi
|
||||
|
||||
echo "${icons[index]}"
|
||||
echo "${icons[index]}"
|
||||
}
|
||||
|
||||
# Will block and listen to the hyprland socket messages and output them
|
||||
|
@ -29,21 +29,22 @@ pick_icon() {
|
|||
# Note: requires openbsd version of netcat.
|
||||
# $1 - Optional event to listen for (no event filtering will be done if not provided)
|
||||
hyprland_ipc() {
|
||||
if [ -z "$HYPRLAND_INSTANCE_SIGNATURE" ]; then
|
||||
>&2 echo "Hyprland is not running, IPC not available"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$HYPRLAND_INSTANCE_SIGNATURE" ]; then
|
||||
>&2 echo "Hyprland is not running, IPC not available"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SOCKET_PATH="/tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock"
|
||||
SOCKET_PATH="${XDG_RUNTIME_DIR:-/run/user/$UID}/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock"
|
||||
#SOCKET_PATH="/tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock"
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
nc -U "$SOCKET_PATH" | while read -r test; do
|
||||
echo "$test"
|
||||
done
|
||||
else
|
||||
nc -U "$SOCKET_PATH" | while read -r test; do
|
||||
# shellcheck disable=SC2016
|
||||
echo "$test" | grep --line-buffered -E "^$1>>" | stdbuf -oL awk -F '>>' '{print $2}'
|
||||
done
|
||||
fi
|
||||
if [ -z "$1" ]; then
|
||||
nc -U "$SOCKET_PATH" | while read -r test; do
|
||||
echo "$test"
|
||||
done
|
||||
else
|
||||
nc -U "$SOCKET_PATH" | while read -r test; do
|
||||
# shellcheck disable=SC2016
|
||||
echo "$test" | grep --line-buffered -E "^$1>>" | stdbuf -oL awk -F '>>' '{print $2}'
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# shellcheck source=include
|
||||
source "./scripts/include"
|
||||
|
@ -7,7 +7,6 @@ source "./scripts/include"
|
|||
# as we might be in transition state and just killing the program might
|
||||
# not be enough.
|
||||
|
||||
|
||||
if [ "$1" = "toggle" ]; then
|
||||
gammastep -x
|
||||
gammastep -x
|
||||
fi
|
||||
|
|
|
@ -1,35 +1,35 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
MOUNTPOINTS=("/" "/mnt/ext")
|
||||
|
||||
data="$(df -H)"
|
||||
|
||||
as_json() {
|
||||
mountpoint="$1"
|
||||
res="$2"
|
||||
arr_res=($res)
|
||||
mountpoint="$1"
|
||||
res="$2"
|
||||
arr_res=($res)
|
||||
|
||||
jq -n -c --monochrome-output \
|
||||
--arg mountpoint "$mountpoint" \
|
||||
--arg size "${arr_res[0]}" \
|
||||
--arg used "${arr_res[1]}" \
|
||||
--arg avail "${arr_res[2]}" \
|
||||
--arg percent "${arr_res[3]}" \
|
||||
'$ARGS.named'
|
||||
jq -n -c --monochrome-output \
|
||||
--arg mountpoint "$mountpoint" \
|
||||
--arg size "${arr_res[0]}" \
|
||||
--arg used "${arr_res[1]}" \
|
||||
--arg avail "${arr_res[2]}" \
|
||||
--arg percent "${arr_res[3]}" \
|
||||
'$ARGS.named'
|
||||
}
|
||||
|
||||
output_json="[]"
|
||||
for mountpoint in "${MOUNTPOINTS[@]}"; do
|
||||
res="$(echo "$data" | awk -v m="$mountpoint" '$6 == m {print $2 " " $3 " " $4 " " $5}')"
|
||||
out="$(as_json "$mountpoint" "$res")"
|
||||
res="$(echo "$data" | awk -v m="$mountpoint" '$6 == m {print $2 " " $3 " " $4 " " $5}')"
|
||||
out="$(as_json "$mountpoint" "$res")"
|
||||
|
||||
# echo "$output_json $out" | jq -c -s
|
||||
# echo "$output_json $out" | jq -c -s
|
||||
|
||||
jq --argjson arr1 "$output_json" --argjson arr2 "[$out]" -n \
|
||||
'$arr1 + $arr2'
|
||||
jq --argjson arr1 "$output_json" --argjson arr2 "[$out]" -n \
|
||||
'$arr1 + $arr2'
|
||||
|
||||
# mount_data+=("$mountpoint" $res)
|
||||
# echo "${mount_data[@]}"
|
||||
# mount_data+=("$mountpoint" $res)
|
||||
# echo "${mount_data[@]}"
|
||||
done
|
||||
|
||||
# echo "${mount_data[@]}"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# shellcheck source=include
|
||||
source "./scripts/include"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Define some icons
|
||||
SPEAKER_ICONS=("" "" "")
|
||||
|
@ -10,100 +10,103 @@ MIC_MUTED_ICON=""
|
|||
|
||||
# $1 can either be "SINK" (speaker) or "SOURCE" (microphone)
|
||||
get_vol() {
|
||||
wpctl get-volume "@DEFAULT_AUDIO_${1}@" | awk '{print int($2*100)}'
|
||||
wpctl get-volume "@DEFAULT_AUDIO_${1}@" | awk '{print int($2*100)}'
|
||||
}
|
||||
|
||||
# $1 can either be "SINK" (speaker) or "SOURCE" (microphone)
|
||||
# #2 is the voulme (as percentage) to set the volume to
|
||||
# $3 is optional, if set, it can be '+' or '-', which then adds/decreases volume, instead of setting
|
||||
set_vol() {
|
||||
wpctl set-volume "@DEFAULT_AUDIO_${1}@" "$(awk -v n="$2" 'BEGIN{print (n / 100)}')$3"
|
||||
wpctl set-volume "@DEFAULT_AUDIO_${1}@" "$(awk -v n="$2" 'BEGIN{print (n / 100)}')$3"
|
||||
}
|
||||
|
||||
# $1 can either be "SINK" (speaker) or "SOURCE" (microphone)
|
||||
check_mute() {
|
||||
wpctl get-volume "@DEFAULT_AUDIO_${1}@" | grep -i muted >/dev/null
|
||||
echo $?
|
||||
wpctl get-volume "@DEFAULT_AUDIO_${1}@" | grep -i muted >/dev/null
|
||||
echo $?
|
||||
}
|
||||
|
||||
# $1 can either be "SINK" (speaker) or "SOURCE" (microphone)
|
||||
toggle_mute() {
|
||||
wpctl set-mute "@DEFAULT_AUDIO_${1}@" toggle
|
||||
wpctl set-mute "@DEFAULT_AUDIO_${1}@" toggle
|
||||
}
|
||||
|
||||
get_report() {
|
||||
spkr_vol="$(get_vol "SINK")"
|
||||
mic_vol="$(get_vol "SOURCE")"
|
||||
spkr_vol="$(get_vol "SINK")"
|
||||
mic_vol="$(get_vol "SOURCE")"
|
||||
|
||||
if [ "$(check_mute "SINK")" == "0" ]; then
|
||||
spkr_mute="true"
|
||||
spkr_icon="$SPEAKER_MUTED_ICON"
|
||||
else
|
||||
spkr_mute="false"
|
||||
index="$(awk -v n="$spkr_vol" -v m="${#SPEAKER_ICONS[@]}" 'BEGIN{print int(n/(100/m))}')"
|
||||
if [ "$(check_mute "SINK")" == "0" ]; then
|
||||
spkr_mute="true"
|
||||
spkr_icon="$SPEAKER_MUTED_ICON"
|
||||
else
|
||||
spkr_mute="false"
|
||||
index="$(awk -v n="$spkr_vol" -v m="${#SPEAKER_ICONS[@]}" 'BEGIN{print int(n/(100/m))}')"
|
||||
|
||||
# We might end up with an higher than the length of icons, if the volume is over 100%
|
||||
# in this case, set the index to last icon
|
||||
if [ "$index" -ge "${#SPEAKER_ICONS[@]}" ]; then
|
||||
spkr_icon="${SPEAKER_ICONS[-1]}"
|
||||
else
|
||||
spkr_icon="${SPEAKER_ICONS[$index]}"
|
||||
fi
|
||||
fi
|
||||
# We might end up with an higher than the length of icons, if the volume is over 100%
|
||||
# in this case, set the index to last icon
|
||||
if [ "$index" -ge "${#SPEAKER_ICONS[@]}" ]; then
|
||||
spkr_icon="${SPEAKER_ICONS[-1]}"
|
||||
else
|
||||
spkr_icon="${SPEAKER_ICONS[$index]}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$(check_mute "SOURCE")" = "0" ]; then
|
||||
mic_mute="true"
|
||||
mic_icon="$MIC_MUTED_ICON"
|
||||
else
|
||||
mic_mute="false"
|
||||
mic_icon="$MIC_ICON"
|
||||
fi
|
||||
if [ "$(check_mute "SOURCE")" = "0" ]; then
|
||||
mic_mute="true"
|
||||
mic_icon="$MIC_MUTED_ICON"
|
||||
else
|
||||
mic_mute="false"
|
||||
mic_icon="$MIC_ICON"
|
||||
fi
|
||||
|
||||
echo "{ \"speaker_vol\": \"$spkr_vol\", \"speaker_mute\": $spkr_mute, \"speaker_icon\": \"$spkr_icon\", \"microphone_mute\": $mic_mute, \"microphone_vol\": \"$mic_vol\", \"microphone_icon\": \"$mic_icon\" }"
|
||||
echo "{ \"speaker_vol\": \"$spkr_vol\", \"speaker_mute\": $spkr_mute, \"speaker_icon\": \"$spkr_icon\", \"microphone_mute\": $mic_mute, \"microphone_vol\": \"$mic_vol\", \"microphone_icon\": \"$mic_icon\" }"
|
||||
}
|
||||
|
||||
# Continually run and report every volume change (into stdout)
|
||||
loop() {
|
||||
get_report
|
||||
pactl subscribe | grep --line-buffered "change" | while read -r _; do
|
||||
get_report
|
||||
done
|
||||
get_report
|
||||
pactl subscribe | grep --line-buffered "change" | while read -r _; do
|
||||
get_report
|
||||
done
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
"loop") loop ;;
|
||||
"loop") loop ;;
|
||||
|
||||
"once") get_report ;;
|
||||
"once") get_report ;;
|
||||
|
||||
"togglemute")
|
||||
if [ "$2" != "SOURCE" ] && [ "$2" != "SINK" ]; then
|
||||
>&2 echo "Invalid usage, expected second argument to be 'SINK' or 'SOURCE', got '$2'"
|
||||
exit 1
|
||||
fi
|
||||
toggle_mute "$2"
|
||||
;;
|
||||
"togglemute")
|
||||
if [ "$2" != "SOURCE" ] && [ "$2" != "SINK" ]; then
|
||||
>&2 echo "Invalid usage, expected second argument to be 'SINK' or 'SOURCE', got '$2'"
|
||||
exit 1
|
||||
fi
|
||||
toggle_mute "$2"
|
||||
;;
|
||||
|
||||
"setvol")
|
||||
if [ "$2" != "SOURCE" ] && [ "$2" != "SINK" ]; then
|
||||
>&2 echo "Invalid usage, expected second argument to be 'SINK' or 'SOURCE', got '$2'"
|
||||
exit 1
|
||||
fi
|
||||
"setvol")
|
||||
if [ "$2" != "SOURCE" ] && [ "$2" != "SINK" ]; then
|
||||
>&2 echo "Invalid usage, expected second argument to be 'SINK' or 'SOURCE', got '$2'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$3" =~ ^[+-]?[0-9]*\.?[0-9]+$ ]]; then
|
||||
case "$4" in
|
||||
"") set_vol "$2" "$3" ;;
|
||||
up|+) set_vol "$2" "$3" "+" ;;
|
||||
down|-) set_vol "$2" "$3" "-" ;;
|
||||
*)
|
||||
>&2 echo "Invalid usage, expected fourth argument to be up/down or +/-, got '$4'"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
else
|
||||
>&2 echo "Invalid usage, exepcted third argument to be a number, got '$3'"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
if [[ "$3" =~ ^[+-]?[0-9]*\.?[0-9]+$ ]]; then
|
||||
case "$4" in
|
||||
"") set_vol "$2" "$3" ;;
|
||||
up | +) set_vol "$2" "$3" "+" ;;
|
||||
down | -) set_vol "$2" "$3" "-" ;;
|
||||
*)
|
||||
>&2 echo "Invalid usage, expected fourth argument to be up/down or +/-, got '$4'"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
else
|
||||
>&2 echo "Invalid usage, exepcted third argument to be a number, got '$3'"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
*) >&2 echo "Invalid usage, argument '$1' not recognized."; exit 1 ;;
|
||||
*)
|
||||
>&2 echo "Invalid usage, argument '$1' not recognized."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# shellcheck source=include
|
||||
source "./scripts/include"
|
||||
|
|
|
@ -7,6 +7,7 @@ the window names. Window name and class are obtained from piped stdin, to preven
|
|||
needlessly keep restarting this program, which takes a while due to the interpreter starting
|
||||
overhead.
|
||||
"""
|
||||
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
|
@ -50,9 +51,9 @@ class RemapRule:
|
|||
# Rules will be applied in specified order
|
||||
REMAP_RULES: list[RemapRule] = [
|
||||
RemapRule(r"", "", ""),
|
||||
RemapRule(r"(.*) — Mozilla Firefox", " {}", "firefox"),
|
||||
RemapRule(r"Mozilla Firefox", " Mozilla Firefox", "firefox"),
|
||||
RemapRule(r"Alacritty", " Alacritty", "Alacritty"),
|
||||
RemapRule(r"(.*) — Mozilla Firefox", " {}", "firefox"),
|
||||
RemapRule(r"Mozilla Firefox", " Mozilla Firefox", "firefox"),
|
||||
RemapRule(r"Alacritty", " Alacritty", "Alacritty"),
|
||||
RemapRule(
|
||||
r"zsh;#toggleterm#1 - \(term:\/\/(.+)\/\/(\d+):(.+)\) - N?VIM",
|
||||
" Terminal: {0}",
|
||||
|
@ -63,13 +64,13 @@ REMAP_RULES: list[RemapRule] = [
|
|||
RemapRule(r"(.+) - Discord", " {}", "discord"),
|
||||
RemapRule(r"(?:\(\d+\) )?Discord \| (.+)", " {}", "vesktop"),
|
||||
RemapRule(r"(.+) - mpv", " {}", "mpv"),
|
||||
RemapRule(r"Stremio - (.+)", " Stremio - {}", r"(Stremio)|(com.stremio.stremio)"),
|
||||
RemapRule(r"Spotify", " Spotify", "Spotify"),
|
||||
RemapRule(r"pulsemixer", " Pulsemixer"),
|
||||
RemapRule(r"Stremio - (.+)", " Stremio - {}", r"(Stremio)|(com.stremio.stremio)"),
|
||||
RemapRule(r"Spotify((?: Premium)?)", " Spotify{}", "[Ss]potify"),
|
||||
RemapRule(r"pulsemixer", " Pulsemixer"),
|
||||
RemapRule(r"(.*)", " {}", "Pcmanfm"),
|
||||
RemapRule(r"(.*)", " {}", "pcmanfm-qt"),
|
||||
# Needs to be last
|
||||
RemapRule(r"(.*)", " {}", "kitty"),
|
||||
RemapRule(r"(.*)", " {}", "kitty"),
|
||||
]
|
||||
|
||||
MAX_LENGTH = 65
|
||||
|
@ -81,7 +82,9 @@ def iter_window() -> Iterator[tuple[str, str]]:
|
|||
line = line.removesuffix("\n")
|
||||
els = line.split(",", maxsplit=1)
|
||||
if len(els) != 2:
|
||||
raise ValueError(f"Expected 2 arguments from stdin line (name, class), but got {len(els)}")
|
||||
raise ValueError(
|
||||
f"Expected 2 arguments from stdin line (name, class), but got {len(els)}"
|
||||
)
|
||||
yield els[1], els[0]
|
||||
|
||||
|
||||
|
@ -94,6 +97,7 @@ def main() -> None:
|
|||
formatted_name = new_name
|
||||
break
|
||||
|
||||
formatted_name = formatted_name.split("\n")[0]
|
||||
if len(formatted_name) > MAX_LENGTH:
|
||||
formatted_name = formatted_name[: MAX_LENGTH - 3] + "..."
|
||||
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# shellcheck source=include
|
||||
source "./scripts/include"
|
||||
|
||||
if [ "$1" = "--switch" ]; then
|
||||
$HOME/.local/bin/scripts/gui/hyprland/swap-workspace "$2" >/dev/null
|
||||
# hyprctl dispatch workspace "$2" >/dev/null
|
||||
hyprctl dispatch focusworkspaceoncurrentmonitor "$2" >/dev/null
|
||||
elif [ "$1" = "--loop" ]; then
|
||||
hyprland_ipc "workspace|createworkspace|destroyworkspace" | ./scripts/workspaces.py "$@"
|
||||
hyprland_ipc "workspace|createworkspace|destroyworkspace" | ./scripts/workspaces.py "$@"
|
||||
else
|
||||
./scripts/workspaces.py "$@"
|
||||
./scripts/workspaces.py "$@"
|
||||
fi
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
|
||||
|
||||
<fontconfig>
|
||||
<description>Disable Caskaydia Cove Nerd Font</description>
|
||||
|
||||
<selectfont>
|
||||
<rejectfont>
|
||||
<glob>/usr/share/fonts/nerd-fonts-git/TTF/Caskaydia*</glob>
|
||||
</rejectfont>
|
||||
</selectfont>
|
||||
</fontconfig>
|
|
@ -50,6 +50,7 @@
|
|||
bD = "branch --delete --force"
|
||||
bm = "branch --move"
|
||||
bM = "branch --move --force"
|
||||
bb = "!better-git-branch"
|
||||
|
||||
r = "rebase"
|
||||
ri = "rebase -i"
|
||||
|
@ -65,8 +66,13 @@
|
|||
|
||||
set-upstream = "!git branch --set-upstream-to=origin/`git symbolic-ref --short HEAD`"
|
||||
|
||||
fixup-picker = "!git log -n 50 --pretty=format:'%h %s' --no-merges | fzf | cut -c -7 | xargs -o git commit --fixup";
|
||||
|
||||
staash = "stash --all";
|
||||
stash-staged = "!sh -c 'git stash --keep-index; git stash push -m \"staged\" --keep-index; git stash pop stash@{1}'"
|
||||
|
||||
reauthor-all = "rebase --root -r --exec 'git commit --amend --no-edit --reset-author --no-verify'";
|
||||
|
||||
find-merge = "!sh -c 'commit=$0 && branch=${1:-HEAD} && (git rev-list $commit..$branch --ancestry-path | cat -n; git rev-list $commit..$branch --first-parent | cat -n) | sort -k2 -s | uniq -f1 -d | sort -n | tail -1 | cut -f2'"
|
||||
show-merge = "!sh -c 'merge=$(git find-merge $0 $1) && [ -n \"$merge\" ] && git show $merge'"
|
||||
|
||||
|
@ -75,7 +81,7 @@
|
|||
total-lines = "!git tracked-text-files | xargs cat | wc -l"
|
||||
total-files = "!git tracked-files | wc -l"
|
||||
total-commits = "!git log --oneline | wc -l"
|
||||
comitter-lines = "!git log --author=\"$1\" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf \"added lines: %s, removed lines: %s, total lines: %s\\n\", add, subs, loc }' #"
|
||||
comitter-lines = "!git log --author=\"$1\" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf \"added lines: %s, removed lines: %s, total lines: %s\\n\", add, subs, loc }' #"
|
||||
[credential]
|
||||
helper = store --file ~/.config/git/git-credentials
|
||||
[core]
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
[Filechooser Settings]
|
||||
LocationMode=path-bar
|
||||
ShowHidden=false
|
||||
ShowSizeColumn=true
|
||||
GeometryX=510
|
||||
GeometryY=260
|
||||
GeometryWidth=900
|
||||
GeometryHeight=584
|
||||
SortColumn=name
|
||||
SortOrder=ascending
|
||||
StartupMode=recent
|
|
@ -1,19 +1,15 @@
|
|||
# DO NOT EDIT! This file will be overwritten by LXAppearance.
|
||||
# Any customization should be done in ~/.gtkrc-2.0.mine instead.
|
||||
|
||||
include "/home/itsdrike/.gtkrc-2.0.mine"
|
||||
gtk-theme-name="Adwaita-dark"
|
||||
gtk-icon-theme-name="Papirus-Dark"
|
||||
gtk-font-name="Noto Sans, 10"
|
||||
gtk-cursor-theme-name="BreezeX-Light"
|
||||
gtk-cursor-theme-size=24
|
||||
gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ
|
||||
gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
|
||||
gtk-theme-name = "Tokyonight-Dark"
|
||||
gtk-icon-theme-name = "Papirus-Dark"
|
||||
gtk-cursor-theme-name = "BreezeX-RosePine-Linux"
|
||||
gtk-cursor-theme-size = 24
|
||||
gtk-font-name = "Noto Sans 10"
|
||||
gtk-button-images=1
|
||||
gtk-menu-images=1
|
||||
gtk-enable-event-sounds=1
|
||||
gtk-enable-input-feedback-sounds=1
|
||||
gtk-enable-event-sounds=0
|
||||
gtk-enable-input-feedback-sounds=0
|
||||
gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
|
||||
gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ
|
||||
gtk-xft-antialias=1
|
||||
gtk-xft-hinting=1
|
||||
gtk-xft-hintstyle="hintfull"
|
||||
gtk-modules="colorreload-gtk-module:window-decorations-gtk-module:appmenu-gtk-module"
|
||||
gtk-xft-hintstyle="hintslight"
|
||||
gtk-xft-rgba="rgb"
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
[Settings]
|
||||
gtk-application-prefer-dark-theme=true
|
||||
gtk-button-images=1
|
||||
gtk-cursor-theme-name=BreezeX-Light
|
||||
gtk-cursor-theme-size=24
|
||||
gtk-decoration-layout=icon:minimize,maximize,close
|
||||
gtk-enable-animations=true
|
||||
gtk-font-name=Noto Sans, 10
|
||||
gtk-theme-name=Tokyonight-Dark
|
||||
gtk-icon-theme-name=Papirus-Dark
|
||||
gtk-cursor-theme-name=BreezeX-RosePine-Linux
|
||||
gtk-cursor-theme-size=24
|
||||
gtk-font-name=Noto Sans 10
|
||||
gtk-enable-animations=true
|
||||
gtk-button-images=1
|
||||
gtk-menu-images=1
|
||||
gtk-modules=colorreload-gtk-module:window-decorations-gtk-module:appmenu-gtk-module
|
||||
gtk-primary-button-warps-slider=false
|
||||
gtk-shell-shows-menubar=1
|
||||
gtk-theme-name=Adwaita-dark
|
||||
gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ
|
||||
gtk-enable-event-sounds=0
|
||||
gtk-enable-input-feedback-sounds=0
|
||||
gtk-error-bell=0
|
||||
gtk-decoration-layout=appmenu:none
|
||||
gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
|
||||
gtk-enable-event-sounds=1
|
||||
gtk-enable-input-feedback-sounds=1
|
||||
gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ
|
||||
gtk-xft-antialias=1
|
||||
gtk-xft-hinting=1
|
||||
gtk-xft-hintstyle=hintfull
|
||||
gtk-xft-hintstyle=hintslight
|
||||
|
|
5
home/.config/gtk-4.0/gtk.css
Normal file
5
home/.config/gtk-4.0/gtk.css
Normal file
|
@ -0,0 +1,5 @@
|
|||
/**
|
||||
* GTK 4 reads the theme configured by gtk-theme-name, but ignores it.
|
||||
* It does however respect user CSS, so import the theme from here.
|
||||
**/
|
||||
@import url("file:///usr/share/themes/Tokyonight-Dark/gtk-4.0/gtk.css");
|
14
home/.config/gtk-4.0/settings.ini
Normal file
14
home/.config/gtk-4.0/settings.ini
Normal file
|
@ -0,0 +1,14 @@
|
|||
[Settings]
|
||||
gtk-application-prefer-dark-theme=true
|
||||
gtk-theme-name=Tokyonight-Dark
|
||||
gtk-icon-theme-name=Papirus-Dark
|
||||
gtk-cursor-theme-name=BreezeX-RosePine-Linux
|
||||
gtk-cursor-theme-size=24
|
||||
gtk-font-name=Noto Sans 10
|
||||
gtk-enable-event-sounds=0
|
||||
gtk-enable-input-feedback-sounds=0
|
||||
gtk-error-bell=0
|
||||
gtk-decoration-layout=appmenu:none
|
||||
gtk-xft-antialias=1
|
||||
gtk-xft-hinting=1
|
||||
gtk-xft-hintstyle=hintslight
|
|
@ -1,19 +1,19 @@
|
|||
{
|
||||
"preset": "rainbow",
|
||||
"mode": "rgb",
|
||||
"light_dark": "dark",
|
||||
"lightness": 0.65,
|
||||
"color_align": {
|
||||
"mode": "custom",
|
||||
"custom_colors": {
|
||||
"1": 1,
|
||||
"2": 4
|
||||
},
|
||||
"fore_back": []
|
||||
"preset": "rainbow",
|
||||
"mode": "rgb",
|
||||
"light_dark": "dark",
|
||||
"lightness": 0.65,
|
||||
"color_align": {
|
||||
"mode": "custom",
|
||||
"custom_colors": {
|
||||
"1": 1,
|
||||
"2": 4
|
||||
},
|
||||
"backend": "neofetch",
|
||||
"args": null,
|
||||
"distro": null,
|
||||
"pride_month_shown": [],
|
||||
"pride_month_disable": false
|
||||
"fore_back": []
|
||||
},
|
||||
"backend": "neofetch",
|
||||
"args": null,
|
||||
"distro": null,
|
||||
"pride_month_shown": [],
|
||||
"pride_month_disable": false
|
||||
}
|
|
@ -4,6 +4,7 @@ general {
|
|||
unlock-cmd = killall -s SIGUSR1 hyprlock && dunstctl set-paused false
|
||||
before_sleep_cmd = loginctl lock-session && dunstctl set-paused true && sleep 2
|
||||
ignore_dbus_inhibit = false
|
||||
ignore_systemd_inhibit = false;
|
||||
}
|
||||
|
||||
# Warn about going idle (5 mins)
|
||||
|
|
|
@ -1,55 +1,6 @@
|
|||
# #################
|
||||
# ### AUTOSTART ###
|
||||
# #################
|
||||
|
||||
exec-once = dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
|
||||
exec-once = systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP XDG_SESSION_TYPE
|
||||
exec-once = sleep 1 && systemctl --user start wayland-session.target # Hyprland socket sometimes isn't yet loaded, sleep for sec
|
||||
|
||||
# exec-once = aa-notify -p
|
||||
# exec-once = udiskie -A -T
|
||||
# exec-once = nm-applet --indicator
|
||||
|
||||
exec-once = vesktop
|
||||
# exec-once = discord
|
||||
# exec-once = webcord --start-minimized
|
||||
|
||||
# #############################
|
||||
# ### ENVIRONMENT VARIABLES ###
|
||||
# #############################
|
||||
|
||||
env = HYPRCURSOR_THEME,Adwaita
|
||||
env = HYPRCURSOR_SIZE,24
|
||||
|
||||
|
||||
# #########################
|
||||
# ### CATEGORY SETTINGS ###
|
||||
# #########################
|
||||
|
||||
general {
|
||||
# cursor_inactive_timeout = 10
|
||||
# no_cursor_warps = true
|
||||
|
||||
layout = dwindle
|
||||
}
|
||||
|
||||
gestures {
|
||||
workspace_swipe = true
|
||||
workspace_swipe_fingers = 3
|
||||
workspace_swipe_distance = 300
|
||||
workspace_swipe_invert = false
|
||||
workspace_swipe_min_speed_to_force = 20
|
||||
workspace_swipe_cancel_ratio = 0.650000
|
||||
}
|
||||
|
||||
group {
|
||||
insert_after_current = true
|
||||
focus_removed_window = true
|
||||
}
|
||||
|
||||
misc {
|
||||
# follow requests from windows to be focused
|
||||
focus_on_activate = true
|
||||
}
|
||||
|
||||
debug {
|
||||
|
@ -58,21 +9,14 @@ debug {
|
|||
enable_stdout_logs = true
|
||||
}
|
||||
|
||||
dwindle {
|
||||
pseudotile = false
|
||||
preserve_split = true
|
||||
no_gaps_when_only = false
|
||||
#smart_split = true
|
||||
}
|
||||
|
||||
# #######################
|
||||
# ### EXTERNAL CONFIG ###
|
||||
# #######################
|
||||
|
||||
source = ~/.config/hypr/input.conf
|
||||
source = ~/.config/hypr/style.conf
|
||||
source = ~/.config/hypr/keybinds.conf
|
||||
source = ~/.config/hypr/window_rules.conf
|
||||
source = ~/.config/hypr/plugins.conf
|
||||
source = ~/.config/hypr/hyprland.d/exec.conf
|
||||
source = ~/.config/hypr/hyprland.d/layout.conf
|
||||
source = ~/.config/hypr/hyprland.d/input.conf
|
||||
source = ~/.config/hypr/hyprland.d/style.conf
|
||||
source = ~/.config/hypr/hyprland.d/keybinds.conf
|
||||
source = ~/.config/hypr/hyprland.d/window_rules.conf
|
||||
source = ~/.config/hypr/hyprland.d/gestures.conf
|
||||
source = ~/.config/hypr/hyprland.d/misc.conf
|
||||
source = ~/.config/hypr/hyprland.d/plugins.conf
|
||||
|
||||
# vi: ft=hyprlang
|
||||
|
|
11
home/.config/hypr/hyprland.d/exec.conf
Normal file
11
home/.config/hypr/hyprland.d/exec.conf
Normal file
|
@ -0,0 +1,11 @@
|
|||
exec-once = systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP XDG_SESSION_TYPE GTK_THEME QT_QPA_PLATFORMTHEME QT_STYLE_OVERRIDE
|
||||
exec-once = dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP GTK_THEME QT_QPA_PLATFORMTHEME QT_STYLE_OVERRIDE
|
||||
|
||||
# Hyprland socket sometimes isn't yet loaded, sleep for sec
|
||||
exec-once = sleep 1 && systemctl --user start wayland-session.target
|
||||
|
||||
exec-once = vesktop
|
||||
# exec-once = discord
|
||||
# exec-once = webcord --start-minimized
|
||||
|
||||
# vi: ft=hyprlang
|
11
home/.config/hypr/hyprland.d/gestures.conf
Normal file
11
home/.config/hypr/hyprland.d/gestures.conf
Normal file
|
@ -0,0 +1,11 @@
|
|||
gestures {
|
||||
workspace_swipe = true
|
||||
workspace_swipe_fingers = 3
|
||||
workspace_swipe_distance = 300
|
||||
workspace_swipe_invert = false
|
||||
workspace_swipe_min_speed_to_force = 20
|
||||
workspace_swipe_cancel_ratio = 0.650000
|
||||
}
|
||||
|
||||
# vi: ft=hyprlang
|
||||
|
|
@ -24,7 +24,10 @@ input {
|
|||
|
||||
follow_mouse = 1
|
||||
touchpad {
|
||||
middle_button_emulation = true
|
||||
# Sending LMB + RMB = MMB
|
||||
middle_button_emulation = true
|
||||
# I'm not natural
|
||||
natural_scroll = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,14 +4,20 @@ $MOUSE_MMB = mouse:274
|
|||
$MOUSE_EX1 = mouse:275
|
||||
$MOUSE_EX2 = mouse:276
|
||||
|
||||
$XF86Favorites = 164
|
||||
|
||||
# #####################
|
||||
# ### DE/WM CONTROL ###
|
||||
# ### ACTIVE WINDOW ###
|
||||
# #####################
|
||||
|
||||
bind = SUPER_SHIFT, Q, exec, menuquit
|
||||
bind = SUPER_CTRL, L, exec, loginctl lock-session
|
||||
bind = SUPER_SHIFT, L, exec, wlogout -p layer-shell
|
||||
bind = SUPER_SHIFT, T, exec, toggle-idle
|
||||
bind = SUPER, W, killactive,
|
||||
bind = SUPER, F, togglefloating,
|
||||
bind = SUPER, Space, fullscreen, 0 # regular fullscreen
|
||||
bind = SUPER_SHIFT, Space, fullscreen, 1 # maximize without client fullscreen
|
||||
bind = SUPER_CTRL, Space, fullscreenstate, 2, 0 # fullscreen without client knowing
|
||||
bind = SUPER_CTRL_SHIFT, Space, fullscreenstate, 1, 2 # maximize with client being full-screen
|
||||
bind = CTRL_SHIFT, Space, exec, toggle-fake-fullscreen # fake fullscreen + custom border
|
||||
bind = SUPER_SHIFT, S, layoutmsg, togglesplit
|
||||
|
||||
# ################
|
||||
# ### PROGRAMS ###
|
||||
|
@ -24,11 +30,41 @@ bind = SUPER_SHIFT, V, exec, clipman pick -t wofi
|
|||
bind = SUPER, Return, exec, kitty
|
||||
bind = SUPER, X, exec, pcmanfm-qt
|
||||
bind = SUPER, B, exec, firefox
|
||||
bind = SUPER, S, exec, spotify
|
||||
bind = SUPER, D, exec, vesktop
|
||||
bind = SUPER, C, exec, qalculate-gtk
|
||||
bind = , XF86Calculator, exec, qalculate-gtk
|
||||
|
||||
# #####################
|
||||
# ### DE/WM CONTROL ###
|
||||
# #####################
|
||||
|
||||
bind = SUPER_SHIFT, Q, exec, menuquit
|
||||
bind = SUPER_CTRL, L, exec, loginctl lock-session
|
||||
bind = SUPER_SHIFT, L, exec, wlogout -p layer-shell
|
||||
bind = SUPER_SHIFT, T, exec, toggle-idle
|
||||
|
||||
# ###################
|
||||
# ### SCREENSHOTS ###
|
||||
# ###################
|
||||
|
||||
# Screenshots (with custom screenshot script)
|
||||
$SCREENSHOT_FORMAT = "${XDG_SCREENSHOTS_DIR:-$HOME/Media/Pictures/Screenshots}/Screenshot_$(date +%Y-%m-%d_%H-%M-%S).png"
|
||||
$SCREENSHOT_DELAY = 2000
|
||||
|
||||
bind = ALT, Print, exec, wl-copy --type image/png "$(hyprpicker)" && notify-send 'Picked color' "$(wl-paste) (saved to clipboard)"
|
||||
bind = , Print, exec, hyprland-screenshot --notify --copy --target area
|
||||
#bindl = , Print, exec, hyprland-screenshot --notify --copy --target all # lockscreen screenshot (only enable when needed)
|
||||
bind = SUPER, Print, exec, hyprland-screenshot --notify --copy --target area --edit
|
||||
bind = SHIFT, Print, exec, hyprland-screenshot --notify --save $SCREENSHOT_FORMAT --target area
|
||||
bind = CTRL, Print, exec, hyprland-screenshot --notify --copy --target area --delay $SCREENSHOT_DELAY
|
||||
bind = SUPER_SHIFT, Print, exec, hyprland-screenshot --notify --save $SCREENSHOT_FORMAT --target area --edit
|
||||
bind = SUPER_CTRL, Print, exec, hyprland-screenshot --notify --copy --target area --delay $SCREENSHOT_DELAY --edit
|
||||
bind = SUPER_SHIFT_CTRL, Print, exec, hyprland-screenshot --notify --save $SCREENSHOT_FORMAT --target area --delay $SCREENSHOT_DELAY --edit
|
||||
# bind = , Print, exec, hyprland-screenshot --save $SCREENSHOT_FORMAT --target all
|
||||
|
||||
# XF86Favorites key for recording
|
||||
# (don't question me, I had it free)
|
||||
bind = , 164, exec, quick-record --notify toggle
|
||||
bind = SUPER, 164, exec, quick-record toggle
|
||||
|
||||
# #####################
|
||||
# ### NOTIFICATIONS ###
|
||||
# #####################
|
||||
|
@ -39,9 +75,9 @@ bind = CTRL, period, exec, dunstctl history-pop
|
|||
bind = CTRL_SHIFT, period, exec, dunstctl context
|
||||
bind = SUPER_SHIFT, D, exec, toggle-notifications
|
||||
|
||||
# ######################
|
||||
# ### VOLUME CONTROL ###
|
||||
# ######################
|
||||
# ############################
|
||||
# ### AUDIO/VOLUME CONTROL ###
|
||||
# ############################
|
||||
|
||||
binde = SUPER, Down, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.05-
|
||||
binde = SUPER, Up, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.05+
|
||||
|
@ -59,48 +95,12 @@ binde = SUPER, Left, exec, brightness -d 5% -n
|
|||
binde = , XF86MonBrightnessUp, exec, brightness -i 5% -n
|
||||
binde = , XF86MonBrightnessDown, exec, brightness -d 5% -n
|
||||
|
||||
# ###################
|
||||
# ### SCREENSHOTS ###
|
||||
# ###################
|
||||
|
||||
# Screenshots (with custom screenshot script)
|
||||
$SCREENSHOT_FORMAT = "${XDG_SCREENSHOTS_DIR:-$HOME/Pictures/Screenshots}/Screenshot_$(date +%Y-%m-%d_%H-%M-%S).png"
|
||||
$SCREENSHOT_DELAY = 2000
|
||||
|
||||
bind = ALT, Print, exec, wl-copy --type image/png "$(hyprpicker)" && notify-send 'Picked color' "$(wl-paste) (saved to clipboard)"
|
||||
bind = , Print, exec, screenshot --notify --copy --target area
|
||||
#bindl = , Print, exec, screenshot --notify --copy --target all # lockscreen screenshot (only enable when needed)
|
||||
bind = SUPER, Print, exec, screenshot --notify --copy --target area --edit
|
||||
bind = SHIFT, Print, exec, screenshot --notify --save $SCREENSHOT_FORMAT --target area
|
||||
bind = CTRL, Print, exec, screenshot --notify --copy --target area --delay $SCREENSHOT_DELAY
|
||||
bind = SUPER_SHIFT, Print, exec, screenshot --notify --save $SCREENSHOT_FORMAT --target area --edit
|
||||
bind = SUPER_CTRL, Print, exec, screenshot --notify --copy --target area --delay $SCREENSHOT_DELAY --edit
|
||||
bind = SUPER_SHIFT_CTRL, Print, exec, screenshot --notify --save $SCREENSHOT_FORMAT --target area --delay $SCREENSHOT_DELAY --edit
|
||||
# bind = , Print, exec, screenshot --save $SCREENSHOT_FORMAT --target all
|
||||
|
||||
# XF86Favorites key for recording
|
||||
# (don't question me, I had it free)
|
||||
bind = , 164, exec, quick-record --notify toggle
|
||||
bind = SUPER, 164, exec, quick-record toggle
|
||||
|
||||
# #####################
|
||||
# ### ACTIVE WINDOW ###
|
||||
# #####################
|
||||
|
||||
bind = SUPER, W, killactive,
|
||||
bind = SUPER, F, togglefloating,
|
||||
bind = SUPER, Space, fullscreen, 0
|
||||
bind = SUPER_SHIFT, Space, fullscreen, 1
|
||||
bind = CTRL_SHIFT, Space, exec, toggle-fakefullscreen
|
||||
bind = SUPER, P, exec, bash -c "if hyprctl activewindow | grep 'floating: 0'; then hyprctl dispatch togglefloating active; fi; hyprctl dispatch pin active"
|
||||
bind = SUPER_SHIFT, P, pseudo,
|
||||
bind = SUPER_SHIFT, S, layoutmsg, togglesplit
|
||||
|
||||
# #####################
|
||||
# ### WINDOW GROUPS ###
|
||||
# #####################
|
||||
|
||||
bind = SUPER, G, togglegroup,
|
||||
bind = SUPER_SHIFT, G, lockactivegroup, toggle
|
||||
bind = ALT, tab, changegroupactive, f
|
||||
bind = ALT, grave, changegroupactive, b
|
||||
|
||||
|
@ -111,15 +111,6 @@ bind = ALT, grave, changegroupactive, b
|
|||
bind = ALT, grave, movetoworkspace, special
|
||||
bind = SUPER, grave, togglespecialworkspace,
|
||||
|
||||
# ################################################################
|
||||
# ### OVERRIDE SPLIT DIRECTION FOR NEXT WINDOW (MANUAL TILING) ###
|
||||
# ################################################################
|
||||
|
||||
bind = SUPER_ALT, left, layoutmsg, preselect l
|
||||
bind = SUPER_ALT, right, layoutmsg, preselect r
|
||||
bind = SUPER_ALT, up, layoutmsg, preselect u
|
||||
bind = SUPER_ALT, down, layoutmsg, preselect d
|
||||
|
||||
# #########################
|
||||
# ### MOVE WINDOW FOCUS ###
|
||||
# #########################
|
||||
|
@ -143,25 +134,34 @@ bind = SUPER_ALT, j, movewindow, d
|
|||
# #######################################
|
||||
|
||||
$myMoveSize = 100
|
||||
$myMove = sh .config/hypr/scripts/move-window.sh $myMoveSize
|
||||
bind = SUPER_ALT, left, exec, $myMove l
|
||||
bind = SUPER_ALT, right, exec, $myMove r
|
||||
bind = SUPER_ALT, up, exec, $myMove u
|
||||
bind = SUPER_ALT, down, exec, $myMove d
|
||||
bind = SUPER_ALT, left, exec, hyprland-move-window $myMoveSiez l
|
||||
bind = SUPER_ALT, right, exec, hyprland-move-window $myMoveSize r
|
||||
bind = SUPER_ALT, up, exec, hyprland-move-window $myMoveSize u
|
||||
bind = SUPER_ALT, down, exec, hyprland-move-window $myMoveSize d
|
||||
|
||||
|
||||
# ################################################################
|
||||
# ### OVERRIDE SPLIT DIRECTION FOR NEXT WINDOW (MANUAL TILING) ###
|
||||
# ################################################################
|
||||
|
||||
bind = SUPER_ALT, left, layoutmsg, preselect l
|
||||
bind = SUPER_ALT, right, layoutmsg, preselect r
|
||||
bind = SUPER_ALT, up, layoutmsg, preselect u
|
||||
bind = SUPER_ALT, down, layoutmsg, preselect d
|
||||
|
||||
# ######################################################
|
||||
# ### SWITCH WORKSPACE (SWAPPING TO CURRENT MONITOR) ###
|
||||
# ######################################################
|
||||
|
||||
bind = SUPER, 1, exec, swap-workspace 1
|
||||
bind = SUPER, 2, exec, swap-workspace 2
|
||||
bind = SUPER, 3, exec, swap-workspace 3
|
||||
bind = SUPER, 4, exec, swap-workspace 4
|
||||
bind = SUPER, 5, exec, swap-workspace 5
|
||||
bind = SUPER, 6, exec, swap-workspace 6
|
||||
bind = SUPER, 7, exec, swap-workspace 7
|
||||
bind = SUPER, 8, exec, swap-workspace 8
|
||||
bind = SUPER, 9, exec, swap-workspace 9
|
||||
bind = SUPER, 1, focusworkspaceoncurrentmonitor, 1
|
||||
bind = SUPER, 2, focusworkspaceoncurrentmonitor, 2
|
||||
bind = SUPER, 3, focusworkspaceoncurrentmonitor, 3
|
||||
bind = SUPER, 4, focusworkspaceoncurrentmonitor, 4
|
||||
bind = SUPER, 5, focusworkspaceoncurrentmonitor, 5
|
||||
bind = SUPER, 6, focusworkspaceoncurrentmonitor, 6
|
||||
bind = SUPER, 7, focusworkspaceoncurrentmonitor, 7
|
||||
bind = SUPER, 8, focusworkspaceoncurrentmonitor, 8
|
||||
bind = SUPER, 9, focusworkspaceoncurrentmonitor, 9
|
||||
|
||||
# ################################
|
||||
# ### MOVE WINDOW TO WORKSPACE ###
|
||||
|
@ -274,7 +274,6 @@ submap = reset
|
|||
# ### GLOBAL KEYBINDS (PASSING KEYS TO OTHER PROGRAMS) ###
|
||||
# ########################################################
|
||||
|
||||
bind = CTRL, F10, pass, ^(com\.obsproject\.Studio)$
|
||||
bind = CTRL, F10, pass, ^(com\.obsproject\.Studio)$
|
||||
|
||||
# #######################
|
||||
|
@ -282,10 +281,10 @@ bind = CTRL, F10, pass, ^(com\.obsproject\.Studio)$
|
|||
# #######################
|
||||
|
||||
# Isolating group to prevent keybind capturing (for games etc)
|
||||
# SUPER + Fn + F12 (Favorites)
|
||||
bind = SUPER, XF86Favorites, exec, hyprctl dispatch submap isolate && notify-send "Keybind isolation" "Keybind isolation on"
|
||||
# SUPER + End
|
||||
bind = SUPER, End, exec, hyprctl dispatch submap isolate && notify-send "Keybind isolation" "Keybind isolation on"
|
||||
submap = isolate
|
||||
bind = SUPER, XF86Favorites, exec, hyprctl dispatch submap reset && notify-send "Keybind isolation" "Keybind isolation off"
|
||||
bind = SUPER, End, exec, hyprctl dispatch submap reset && notify-send "Keybind isolation" "Keybind isolation off"
|
||||
submap = reset
|
||||
|
||||
# vi: ft=hyprlang
|
26
home/.config/hypr/hyprland.d/layout.conf
Normal file
26
home/.config/hypr/hyprland.d/layout.conf
Normal file
|
@ -0,0 +1,26 @@
|
|||
general {
|
||||
layout = dwindle
|
||||
}
|
||||
|
||||
dwindle {
|
||||
# Don't change the split (side/top) regardless
|
||||
# of what happens to the container
|
||||
preserve_split = true
|
||||
|
||||
# Show gaps even when there's only 1 window opened
|
||||
no_gaps_when_only = false
|
||||
|
||||
# Scale down special workspaces (bigger borders)
|
||||
special_scale_factor = 0.9
|
||||
}
|
||||
|
||||
group {
|
||||
# Add new windows in the group after the current window
|
||||
# rather than after the group tail window
|
||||
insert_after_current = true
|
||||
|
||||
# Focus the window that was just moved out of the group
|
||||
focus_removed_window = true
|
||||
}
|
||||
|
||||
# vi: ft=hyprlang
|
14
home/.config/hypr/hyprland.d/misc.conf
Normal file
14
home/.config/hypr/hyprland.d/misc.conf
Normal file
|
@ -0,0 +1,14 @@
|
|||
misc {
|
||||
# Disable redundant renders (covered by wallpaper)
|
||||
disable_hyprland_logo = true
|
||||
disable_splash_rendering = true
|
||||
|
||||
# follow requests from windows to be focused
|
||||
focus_on_activate = true
|
||||
|
||||
# Enable DPMS on these actions
|
||||
mouse_move_enables_dpms = true
|
||||
key_press_enables_dpms = true
|
||||
}
|
||||
|
||||
# vi: ft=hyprlang
|
|
@ -44,18 +44,24 @@ group {
|
|||
|
||||
group {
|
||||
groupbar {
|
||||
render_titles = true
|
||||
font_size = 8
|
||||
text_color = rgba(FFFFFFFF) # white
|
||||
# Title box above window
|
||||
render_titles = false # disable, looks kinda bad
|
||||
font_family = Monaspace Krypton
|
||||
font_size = 11
|
||||
text_color = rgba(FFFFFFFF) # white
|
||||
|
||||
gradients = true
|
||||
scrolling = false
|
||||
# Gradients should be enabled only if title rendering is also enabled
|
||||
# on their own, they look really bad
|
||||
gradients = false
|
||||
|
||||
col.active = rgba(FFA500FF) # light orange
|
||||
col.inactive = rgba(00A500AA) # transparent green
|
||||
|
||||
col.locked_active = rgba(FF8000FF) # dark orange
|
||||
col.locked_inactive = rgba(A0A500AA) # transparent yello
|
||||
col.locked_inactive = rgba(A0A500AA) # transparent yellow
|
||||
|
||||
# Scrolling in the groupbar shouldn't change the active window
|
||||
scrolling = false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,6 +108,7 @@ decoration {
|
|||
|
||||
animations {
|
||||
enabled = true
|
||||
first_launch_animation = true # fade in on first launch
|
||||
|
||||
animation = windows, 1, 3, default, popin 50%
|
||||
animation = border, 1, 4, default
|
||||
|
@ -118,9 +125,4 @@ misc {
|
|||
# ### WALLPAPER ###
|
||||
# #################
|
||||
|
||||
misc {
|
||||
disable_hyprland_logo = true
|
||||
disable_splash_rendering = false
|
||||
}
|
||||
|
||||
# vi: ft=hyprlang
|
|
@ -27,22 +27,6 @@ windowrulev2 = idleinhibit focus, class:^(firefox)$,title:^(Picture-in-Picture)$
|
|||
windowrulev2 = size 800 550, class:^(qalculate-gtk)$
|
||||
windowrulev2 = tile, class:^(Spotify)$
|
||||
|
||||
# #############
|
||||
# ### FIXES ###
|
||||
# #############
|
||||
|
||||
# jetbrains
|
||||
|
||||
windowrulev2 = windowdance, class:^(jetbrains-.*)$,floating:1
|
||||
windowrulev2 = center, class:^(jetbrains-.*)$,title:^(splash)$,floating:1
|
||||
windowrulev2 = nofocus, class:^(jetbrains-.*)$,title:^(splash)$,floating:1
|
||||
windowrulev2 = noborder, class:^(jetbrains-.*)$,title:^(splash)$,floating:1
|
||||
windowrulev2 = center, class:^(jetbrains-.*)$,title:^( )$,floating:1
|
||||
windowrulev2 = stayfocused, class:^(jetbrains-.*)$,title:^( )$,floating:1
|
||||
windowrulev2 = noborder, class:^(jetbrains-.*)$,title:^( )$,floating:1
|
||||
windowrulev2 = nofocus, class:^(jetbrains-.*)$,title:^(win.*)$,floating:1
|
||||
windowrulev2 = noinitialfocus, class:^(jetbrains-.*)$,title:^(win.*)$
|
||||
|
||||
# ##################
|
||||
# ### AUTO FLOAT ###
|
||||
# ##################
|
||||
|
@ -58,10 +42,16 @@ windowrulev2 = float, class:^(com.github.wwmm.easyeffects)
|
|||
windowrulev2 = float, class:^(opensnitch_ui)$
|
||||
windowrulev2 = float, class:^(Brave-browser)$,title:^(_crx_.+)$
|
||||
|
||||
## Float hyprland-share-picker & some extra actions
|
||||
windowrulev2 = float, class:^(hyprland-share-picker)$
|
||||
windowrulev2 = center, class:^(hyprland-share-picker)$
|
||||
windowrulev2 = animation slide, class:^(hyprland-share-picker)$
|
||||
|
||||
## Float firefox windows (like bookmark menus, or some extension windows)
|
||||
windowrulev2 = float, class:^(firefox)$,title:^(Revert Bookmarks)$
|
||||
windowrulev2 = float, class:^(firefox)$,title:^(Library)$
|
||||
windowrulev2 = float, class:^(firefox)$,title:^(Extension: \(uBlock Origin\))
|
||||
windowrulev2 = float, class:^(firefox)$,title:^(Extension: \(Bitwarden Password Manager\) - Bitwarden — Mozilla Firefox)$
|
||||
windowrulev2 = float, class:^(firefox)$,title:^(Firefox — Sharing Indicator)$
|
||||
windowrulev2 = float, class:^(firefox)$,title:^(Opening .+)$
|
||||
windowrulev2 = float, class:^(firefox)$,title:^$
|
||||
|
@ -73,6 +63,11 @@ windowrulev2 = float, class:^(pcmanfm-qt)$,title:^(Move files)$
|
|||
windowrulev2 = float, class:^(pcmanfm-qt)$,title:^(Search Files)$
|
||||
windowrulev2 = float, class:^(pcmanfm-qt)$,title:^(Copy Files)$
|
||||
windowrulev2 = float, class:^(pcmanfm-qt)$,title:^(Confirm to replace files)$
|
||||
windowrulev2 = float, class:^(pcmanfm-qt|)$,title:^(Choose an Application)$
|
||||
|
||||
## Float some qimgv windows
|
||||
windowrulev2 = float, class:^(qimgv)$,title:^(Add shortcut)$
|
||||
windowrulev2 = float, class:^(qimgv)$,title:^(Preferences — qimgv)$
|
||||
|
||||
## Float some windows from other apps
|
||||
windowrulev2 = float, class:^(Spotify)$,title:^(Ozone X11)$
|
||||
|
@ -88,5 +83,27 @@ windowrulev2 = float, class:^(notification)$
|
|||
windowrulev2 = float, class:^(error)$
|
||||
windowrulev2 = float, class:^(splash)$
|
||||
windowrulev2 = float, class:^(confirmreset)$
|
||||
windowrulev2 = float, class:^(floating)$
|
||||
|
||||
## Float all windows that don't have a title nor a class
|
||||
windowrulev2 = float, class:^$,title:^$
|
||||
|
||||
# #############
|
||||
# ### FIXES ###
|
||||
# #############
|
||||
|
||||
# jetbrains
|
||||
|
||||
windowrulev2 = center, class:^(jetbrains-.*)$,title:^(splash)$,floating:1
|
||||
windowrulev2 = nofocus, class:^(jetbrains-.*)$,title:^(splash)$,floating:1
|
||||
windowrulev2 = noborder, class:^(jetbrains-.*)$,title:^(splash)$,floating:1
|
||||
windowrulev2 = center, class:^(jetbrains-.*)$,title:^( )$,floating:1
|
||||
windowrulev2 = stayfocused, class:^(jetbrains-.*)$,title:^( )$,floating:1
|
||||
windowrulev2 = noborder, class:^(jetbrains-.*)$,title:^( )$,floating:1
|
||||
windowrulev2 = nofocus, class:^(jetbrains-.*)$,title:^(win.*)$,floating:1
|
||||
windowrulev2 = noinitialfocus, class:^(jetbrains-.*)$,title:^(win.*)$
|
||||
|
||||
# Don't add borders to grim selections when taking screenshots
|
||||
layerrule = noanim, ^(selection)$
|
||||
|
||||
# vi: ft=hyprlang
|
|
@ -9,11 +9,11 @@ general {
|
|||
}
|
||||
|
||||
background {
|
||||
path = ~/Pictures/Wallpapers/Categories/Extra/origami.png
|
||||
path = ~/Media/Pictures/Wallpapers/Categories/Extra/origami.png
|
||||
blur_passes = 3
|
||||
blur_size = 6
|
||||
contrast = 0.7
|
||||
brightness = 0.7
|
||||
#contrast = 0.7
|
||||
#brightness = 0.7
|
||||
noise = 0.01
|
||||
contrast = 0.9
|
||||
brightness = 0.6
|
||||
|
@ -53,7 +53,7 @@ label {
|
|||
font_size = 35
|
||||
font_family = Noto Sans
|
||||
|
||||
position = 0, 0
|
||||
position = 0, 30
|
||||
halign = center
|
||||
valign = center
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ label {
|
|||
font_size = 20
|
||||
font_family = Noto Sans
|
||||
|
||||
position = 0, -50
|
||||
position = 0, -20
|
||||
halign = center
|
||||
valign = center
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ label {
|
|||
valign = center
|
||||
}
|
||||
|
||||
# Failed attempts count
|
||||
# Fail reason
|
||||
label {
|
||||
text = <i>$FAIL</i>
|
||||
color = rgba(255, 34, 34, 1.0) # red
|
||||
|
@ -123,7 +123,7 @@ label {
|
|||
text = Session Locked
|
||||
color = rgba(255, 255, 255, 1.0)
|
||||
font_size = 40
|
||||
font_family = GohuFont uni11 Nerd Font
|
||||
font_family = Monaspace Krypton
|
||||
|
||||
shadow_passes = 1
|
||||
shadow_size = 5
|
||||
|
|
5
home/.config/hypr/hyprpaper.conf
Normal file
5
home/.config/hypr/hyprpaper.conf
Normal file
|
@ -0,0 +1,5 @@
|
|||
$bg = $HOME/Media/Pictures/Wallpapers/active
|
||||
|
||||
preload=$bg
|
||||
wallpaper=,$bg # same wallpaper on all monitors
|
||||
ipc=off
|
|
@ -1,29 +1,88 @@
|
|||
# Fonts
|
||||
font_family JetBrains Mono
|
||||
# Fonts & Text style
|
||||
font_family Monaspace Krypton
|
||||
bold_font auto
|
||||
italic_font auto
|
||||
bold_italic_font auto
|
||||
font_size 11
|
||||
disable_ligatures never
|
||||
|
||||
#font_size 13
|
||||
|
||||
disable_ligatures always
|
||||
|
||||
# Colors / Style
|
||||
# Dark Theme
|
||||
foreground #d8dee9
|
||||
background #191919
|
||||
cursor #D0D0D0
|
||||
# Light Theme (for screenshots in papers)
|
||||
#foreground = "#191919";
|
||||
#background = "#FFFFFF";
|
||||
|
||||
# URLs
|
||||
url_color #0087bd
|
||||
url_style curly
|
||||
|
||||
background_opacity 0.85
|
||||
# Cursor
|
||||
cursor #D0D0D0
|
||||
cursor_shape underline
|
||||
cursor_blink_interval 0.5
|
||||
cursor_stop_blinking_after 15.0
|
||||
|
||||
# Background
|
||||
background_opacity 0.9
|
||||
dynamic_background_opacity yes
|
||||
background_blur 2
|
||||
|
||||
# Misc
|
||||
scrollback_lines 10000
|
||||
# Window size
|
||||
remember_window_size no
|
||||
initial_window_width 640
|
||||
initial_window_height 400
|
||||
|
||||
# Bell
|
||||
## flash the screen for this duration when bell occurs
|
||||
visual_bell_duration 0.0
|
||||
## disable audio bells
|
||||
enable_audio_bell no
|
||||
|
||||
|
||||
# Misc
|
||||
## don't check for updates, we have a package manager...
|
||||
update_check_interval 0
|
||||
## don't ask for confirmation if window gets closed
|
||||
confirm_os_window_close 0
|
||||
## Capture up to 10k lines for scrolling
|
||||
scrollback_lines 10000
|
||||
## chars considered part of word when double clicking
|
||||
select_by_word_characters :@-./_~?&=%+#
|
||||
|
||||
# Keybindings
|
||||
map ctrl+alt+c copy_to_clipboard
|
||||
map ctrl+alt+v paste_from_clipboard
|
||||
map ctrl+c copy_or_interrupt
|
||||
map ctrl+shift+, move_tab_backward
|
||||
map ctrl+shift+. move_tab_forward
|
||||
map ctrl+shift+0 tenth_window
|
||||
map ctrl+shift+1 first_window
|
||||
map ctrl+shift+2 second_window
|
||||
map ctrl+shift+3 third_window
|
||||
map ctrl+shift+4 fourth_window
|
||||
map ctrl+shift+5 fifth_window
|
||||
map ctrl+shift+6 sixth_window
|
||||
map ctrl+shift+7 seventh_window
|
||||
map ctrl+shift+8 eighth_window
|
||||
map ctrl+shift+9 ninth_window
|
||||
map ctrl+shift+[ previous_window
|
||||
map ctrl+shift+] next_window
|
||||
map ctrl+shift+` move_window_to_top
|
||||
map ctrl+shift+alt+t set_tab_title
|
||||
map ctrl+shift+b move_window_backward
|
||||
map ctrl+shift+backspace restore_font_size
|
||||
map ctrl+shift+down decrease_font_size
|
||||
map ctrl+shift+enter new_window
|
||||
map ctrl+shift+f move_window_forward
|
||||
map ctrl+shift+l next_layout
|
||||
map ctrl+shift+left previous_tab
|
||||
map ctrl+shift+n new_os_window
|
||||
map ctrl+shift+q close_tab
|
||||
map ctrl+shift+right next_tab
|
||||
map ctrl+shift+t new_tab
|
||||
map ctrl+shift+up increase_font_size
|
||||
map ctrl+shift+v paste_from_clipboard
|
||||
map ctrl+shift+w close_window
|
||||
|
||||
# vi: ft=conf
|
||||
|
|
|
@ -1,20 +1,185 @@
|
|||
[Default Applications]
|
||||
inode/directory=pcmanfm-qt.desktop
|
||||
image/jpeg=org.nomacs.ImageLounge.desktop
|
||||
image/png=org.nomacs.ImageLounge.desktop
|
||||
image/gif=org.nomacs.ImageLounge.desktop
|
||||
application/pdf=firefox.desktop
|
||||
# Browser
|
||||
text/html=firefox.desktop
|
||||
x-scheme-handler/http=firefox.desktop
|
||||
x-scheme-handler/https=firefox.desktop
|
||||
x-scheme-handler/about=firefox.desktop
|
||||
x-scheme-handler-unknown=firefox.desktop
|
||||
application/json=nvim.desktop
|
||||
application/x-extension-htm=firefox.desktop
|
||||
application/x-extension-html=firefox.desktop
|
||||
application/x-extension-shtml=firefox.desktop
|
||||
application/x-extension-xhtml=firefox.desktop
|
||||
application/x-extension-xht=firefox.desktop
|
||||
application/xhtml+xml=firefox.desktop
|
||||
application/xhtml_xml=firefox.desktop
|
||||
|
||||
# Image viewer
|
||||
# (wildcard associations don't work everywhere)
|
||||
# or org.nomacs.ImageLounge.desktop?
|
||||
image/*=qimgv.desktop
|
||||
image/bmp=qimgv.desktop
|
||||
image/gif=qimgv.desktop
|
||||
image/jpeg=qimgv.desktop
|
||||
image/jpg=qimgv.desktop
|
||||
image/png=qimgv.desktop
|
||||
image/webp=qimgv.desktop
|
||||
image/tiff=qimgv.desktop
|
||||
image/x-bmp=qimgv.desktop
|
||||
image/x-pcx=qimgv.desktop
|
||||
image/x-tga=qimgv.desktop
|
||||
image/x-portable-pixmap=qimgv.desktop
|
||||
image/x-portable-bitmap=qimgv.desktop
|
||||
image/x-portable-greymap=qimgv.desktop
|
||||
image/x-targa=qimgv.desktop
|
||||
image/svg+xml=qimgv.desktop
|
||||
image/svg_xml=qimgv.desktop
|
||||
|
||||
# Media player
|
||||
|
||||
# Media Player (video + audio)
|
||||
# (wildcard associations don't work everywhere)
|
||||
video/*=mpv.desktop
|
||||
video/mpeg=mpv.desktop
|
||||
video/x-mpeg2=mpv.desktop
|
||||
video/x-mpeg3=mpv.desktop
|
||||
video/mp4v-es=mpv.desktop
|
||||
video/x-m4v=mpv.desktop
|
||||
video/mp4=mpv.desktop
|
||||
video/divx=mpv.desktop
|
||||
video/vnd.divx=mpv.desktop
|
||||
video/msvideo=mpv.desktop
|
||||
video/x-msvideo=mpv.desktop
|
||||
video/ogg=mpv.desktop
|
||||
video/quicktime=mpv.desktop
|
||||
video/vnd.rn-realvideo=mpv.desktop
|
||||
video/x-avi=mpv.desktop
|
||||
video/avi=mpv.desktop
|
||||
video/x-flic=mpv.desktop
|
||||
video/fli=mpv.desktop
|
||||
video/x-flc=mpv.desktop
|
||||
video/flv=mpv.desktop
|
||||
video/x-flv=mpv.desktop
|
||||
video/x-theora=mpv.desktop
|
||||
video/x-theora+ogg=mpv.desktop
|
||||
video/x-matroska=mpv.desktop
|
||||
video/mkv=mpv.desktop
|
||||
video/webm=mpv.desktop
|
||||
video/x-ogm=mpv.desktop
|
||||
video/x-ogm+ogg=mpv.desktop
|
||||
video/dv=mpv.desktop
|
||||
video/mp2t=mpv.desktop
|
||||
video/vnd.mpegurl=mpv.desktop
|
||||
video/3gp=mpv.desktop
|
||||
video/3gpp=mpv.desktop
|
||||
video/3gpp2=mpv.desktop
|
||||
|
||||
audio/*=mpv.desktop
|
||||
audio/x-matroska=mpv.desktop
|
||||
audio/webm=mpv.desktop
|
||||
audio/vorbis=mpv.desktop
|
||||
audio/x-vorbis=mpv.desktop
|
||||
audio/x-vorbis+ogg=mpv.desktop
|
||||
audio/x-shorten=mpv.desktop
|
||||
audio/x-ape=mpv.desktop
|
||||
audio/x-wavpack=mpv.desktop
|
||||
audio/x-tta=mpv.desktop
|
||||
audio/AMR=mpv.desktop
|
||||
audio/ac3=mpv.desktop
|
||||
audio/eac3=mpv.desktop
|
||||
audio/amr-wb=mpv.desktop
|
||||
audio/flac=mpv.desktop
|
||||
audio/mp4=mpv.desktop
|
||||
audio/x-pn-au=mpv.desktop
|
||||
audio/3gpp=mpv.desktop
|
||||
audio/3gpp2=mpv.desktop
|
||||
audio/dv=mpv.desktop
|
||||
audio/opus=mpv.desktop
|
||||
audio/x-ms-asf=mpv.desktop
|
||||
audio/vnd.dts=mpv.desktop
|
||||
audio/vnd.dts.hd=mpv.desktop
|
||||
audio/x-adpcm=mpv.desktop
|
||||
audio/m3u=mpv.desktop
|
||||
audio/aac=mpv.desktop
|
||||
audio/x-aac=mpv.desktop
|
||||
audio/vnd.dolby.heaac.1=mpv.desktop
|
||||
audio/vnd.dolby.heaac.2=mpv.desktop
|
||||
audio/aiff=mpv.desktop
|
||||
audio/x-aiff=mpv.desktop
|
||||
audio/m4a=mpv.desktop
|
||||
audio/x-m4a=mpv.desktop
|
||||
audio/mp1=mpv.desktop
|
||||
audio/x-mp1=mpv.desktop
|
||||
audio/mp2=mpv.desktop
|
||||
audio/x-mp2=mpv.desktop
|
||||
audio/mp3=mpv.desktop
|
||||
audio/x-mp3=mpv.desktop
|
||||
audio/mpeg=mpv.desktop
|
||||
audio/mpeg2=mpv.desktop
|
||||
audio/mpeg3=mpv.desktop
|
||||
audio/mpegurl=mpv.desktop
|
||||
audio/x-mpegurl=mpv.desktop
|
||||
audio/mpg=mpv.desktop
|
||||
audio/x-mpg=mpv.desktop
|
||||
audio/rn-mpeg=mpv.desktop
|
||||
audio/musepack=mpv.desktop
|
||||
audio/x-musepack=mpv.desktop
|
||||
audio/ogg=mpv.desktop
|
||||
audio/scpls=mpv.desktop
|
||||
audio/x-scpls=mpv.desktop
|
||||
audio/vnd.rn-realaudio=mpv.desktop
|
||||
audio/wav=mpv.desktop
|
||||
audio/x-pn-wav=mpv.desktop
|
||||
audio/x-pn-windows-pcm=mpv.desktop
|
||||
audio/x-realaudio=mpv.desktop
|
||||
audio/x-pn-realaudio=mpv.desktop
|
||||
audio/x-ms-wma=mpv.desktop
|
||||
audio/x-pls=mpv.desktop
|
||||
audio/x-wav=mpv.desktop
|
||||
|
||||
application/x-cue=mpv.desktop
|
||||
application/vnd.ms-asf=mpv.desktop
|
||||
application/x-matroska=mpv.desktop
|
||||
application/x-ogm=mpv.desktop
|
||||
application/x-ogm-audio=mpv.desktop
|
||||
application/x-ogm-video=mpv.desktop
|
||||
application/x-shorten=mpv.desktop
|
||||
application/x-mpegurl=mpv.desktop
|
||||
application/vnd.apple.mpegurl=mpv.desktop
|
||||
application/ogg=mpv.desktop
|
||||
application/x-ogg=mpv.desktop
|
||||
application/mxf=mpv.desktop
|
||||
application/sdp=mpv.desktop
|
||||
application/smil=mpv.desktop
|
||||
application/x-smil=mpv.desktop
|
||||
application/streamingmedia=mpv.desktop
|
||||
application/x-streamingmedia=mpv.desktop
|
||||
application/vnd.rn-realmedia=mpv.desktop
|
||||
application/vnd.rn-realmedia-vbr=mpv.desktop
|
||||
application/x-extension-m4a=mpv.desktop
|
||||
|
||||
# Document Viewer
|
||||
application/pdf=firefox.desktop
|
||||
application/epub=firefox.desktop
|
||||
application/djvu=firefox.desktop
|
||||
application/mobi=firefox.desktop
|
||||
|
||||
# File & archive manager(s)
|
||||
inode/directory=pcmanfm-qt.desktop
|
||||
application/zip=org.gnome.FileRoller.desktop
|
||||
application/x-xz-compressed-tar=org.gnome.FileRoller.desktop
|
||||
|
||||
# Plain-text
|
||||
text/plain=nvim.desktop
|
||||
application/json=nvim.desktop
|
||||
application/x-desktop=nvim.desktop;
|
||||
|
||||
# Application specific schemes
|
||||
x-scheme-handler/spotify=spotify.desktop
|
||||
x-scheme-handler/tg=telegramdesktop.desktop
|
||||
x-scheme-handler/discord=vesktop.desktop
|
||||
x-scheme-handler/msteams=teams.desktop
|
||||
|
||||
# Misc
|
||||
x-scheme-handler/mailto=firefox.desktop
|
||||
|
||||
[Added Associations]
|
||||
application/x-desktop=nvim.desktop;
|
||||
image/png=org.nomacs.ImageLounge.desktop;
|
||||
text/plain=nvim.desktop;
|
||||
image/svg+xml=org.nomacs.ImageLounge.desktop;
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
[General]
|
||||
DkEditDock=2
|
||||
DkExplorer=1
|
||||
DkMetaDataDock=2
|
||||
firstTime=false
|
||||
geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x3\xc7\0\0\x2\x38\0\0\au\0\0\x4\x32\0\0\x3\xc7\0\0\x2\x38\0\0\au\0\0\x4-\0\0\0\0\x2\0\0\0\a\x80\0\0\x3\xc7\0\0\x2\x38\0\0\au\0\0\x4\x32)
|
||||
geometryNomacs=@Rect(967 568 943 507)
|
||||
windowState=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\x3\0\0\0\0\0\0\x1\0\0\0\x4\x4\xfc\x2\0\0\0\x1\xfb\0\0\0\x14\0\x44\0k\0\x45\0x\0p\0l\0o\0r\0\x65\0r\0\0\0\0\x34\0\0\x4\x4\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\xdd\0\0\x3\xc4\xfc\x2\0\0\0\x1\xfb\0\0\0\x14\0\x44\0k\0\x45\0\x64\0i\0t\0\x44\0o\0\x63\0k\0\0\0\0\x1e\0\0\x3\xc4\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\a\x80\0\0\0>\xfc\x1\0\0\0\x1\xfb\0\0\0\x10\0\x63\0r\0o\0p\0\x44\0o\0\x63\0k\0\0\0\0\0\0\0\a\x80\0\0\0\0\0\0\0\0\0\0\x3\xaf\0\0\x1\xe4\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\x1\0\0\0\x2\0\0\0\x1\0\0\0\x16\0\x45\0\x64\0i\0t\0T\0o\0o\0l\0\x42\0\x61\0r\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0)
|
||||
|
||||
[AppSettings]
|
||||
appMode=0
|
||||
|
@ -12,29 +10,27 @@ currentAppMode=0
|
|||
defaultJpgQuality=97
|
||||
firstTime.nomacs.3=false
|
||||
hideAllPanels=true
|
||||
showPlayer=@Variant(\0\0\0\r\0\0\0\x6\0)
|
||||
showMenuBar=false
|
||||
showRecentFiles=false
|
||||
useLogFile=true
|
||||
|
||||
[CustomPluginShortcuts]
|
||||
Composite%20Image=Composite Image
|
||||
Crop%20to%20Metadata=Crop to Metadata
|
||||
Crop%20to%20Page=Crop to Page
|
||||
Draw%20to%20Page=Draw to Page
|
||||
Fake%20Miniatures=Fake Miniatures
|
||||
Image%20Transform=Image Transform
|
||||
Paint%20on%20Image=Paint on Image
|
||||
[Crop]
|
||||
AspectRatioHorizontal=0
|
||||
AspectRatioVertical=0
|
||||
cropToMetadata=false
|
||||
guides=1
|
||||
info=true
|
||||
inverted=false
|
||||
|
||||
[DisplaySettings]
|
||||
bgColorNoMacsRGBA=4281545523
|
||||
bgColorWidgetRGBA=2852126720
|
||||
fadeSec=@Variant(\0\0\0\x87\0\0\0\0)
|
||||
fadeSec=0
|
||||
fontColorRGBA=4292730333
|
||||
highlightColorRGBA=4278233855
|
||||
iconColorRGBA=4292730333
|
||||
iconSize=18
|
||||
showCrop=true
|
||||
themeName312=Dark-Theme.css
|
||||
transition=0
|
||||
zoomToFit=true
|
||||
|
||||
[DkAppManager]
|
||||
Apps\size=0
|
||||
|
@ -51,14 +47,14 @@ overwriteDialog-answer=16384
|
|||
saveEditDialog=false
|
||||
saveEditDialog-answer=16384
|
||||
saveTabsDialog=false
|
||||
saveTabsDialog-answer=65536
|
||||
saveTabsDialog-answer=16384
|
||||
|
||||
[DkExplorer]
|
||||
Date%20ModifiedHidden=true
|
||||
Date%20ModifiedSize=0
|
||||
LoadSelected=false
|
||||
NameHidden=false
|
||||
NameSize=254
|
||||
NameSize=243
|
||||
ReadOnly=true
|
||||
RootPath=/home/itsdrike
|
||||
SizeHidden=true
|
||||
|
@ -69,20 +65,23 @@ TypeSize=0
|
|||
[DkFilePreview]
|
||||
windowPosition=1
|
||||
|
||||
[DkMetaDataDock]
|
||||
KeySize=100
|
||||
ValueSize=113
|
||||
expandedNames=@Invalid()
|
||||
|
||||
[DkMetaDataHUD]
|
||||
keyValues=File.Filename, File.Path, File.Size, Exif.Image.Make, Exif.Image.Model, Exif.Image.DateTime, Exif.Image.ImageDescription, Exif.Photo.ISO, Exif.Photo.FocalLength, Exif.Photo.ExposureTime, Exif.Photo.Flash, Exif.Photo.FNumber
|
||||
numColumns=-1
|
||||
windowPosition=3
|
||||
|
||||
[GlobalSettings]
|
||||
logRecentFiles=false
|
||||
|
||||
[MetaDataSettings]
|
||||
ignoreExifOrientation=false
|
||||
saveExifOrientation=false
|
||||
|
||||
[Page%20Extraction%20Plugin]
|
||||
Method=0
|
||||
|
||||
[SlideShowSettings]
|
||||
time=@Variant(\0\0\0\x87@\xa0\0\0)
|
||||
|
||||
[SynchronizeSettings]
|
||||
checkForUpdates=true
|
||||
disableUpdateInteraction=false
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
prefix=${XDG_DATA_HOME}/npm
|
||||
cache=${XDG_CACHE_HOME}/npm
|
||||
tmp=${XDG_RUNTIME_DIR}/npm
|
||||
init-module=${XDG_CONFIG_HOME}/npm/config/npm-init.js
|
||||
|
|
|
@ -1,25 +1,30 @@
|
|||
import atexit
|
||||
import os
|
||||
import readline
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
from types import ModuleType
|
||||
def is_vanilla() -> bool:
|
||||
import sys
|
||||
|
||||
cache_xdg_dir = Path(os.environ.get("XDG_CACHE_HOME", str(Path("~/.cache"))))
|
||||
cache_xdg_dir.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
history_file = cache_xdg_dir.joinpath("python_history")
|
||||
|
||||
readline.read_history_file(history_file)
|
||||
return not hasattr(__builtins__, "__IPYTHON__") and "bpython" not in sys.argv[0]
|
||||
|
||||
|
||||
def write_history(readline: ModuleType, history_file: Path) -> None:
|
||||
"""
|
||||
We need to get ``readline`` and ``history_file`` as arguments, as it
|
||||
seems they get garbage collected when the function is registered and
|
||||
the program ends, even though we refer to them here.
|
||||
"""
|
||||
readline.write_history_file(history_file)
|
||||
def setup_history():
|
||||
import os
|
||||
import atexit
|
||||
import readline
|
||||
from pathlib import Path
|
||||
|
||||
if state_home := os.environ.get("XDG_STATE_HOME"):
|
||||
state_home = Path(state_home)
|
||||
else:
|
||||
state_home = Path.home() / ".local" / "state"
|
||||
|
||||
history: Path = state_home / "python_history"
|
||||
|
||||
# https://github.com/python/cpython/issues/105694
|
||||
if not history.is_file():
|
||||
# breaks on macos + python3 without this.
|
||||
readline.write_history_file(str(history))
|
||||
|
||||
readline.read_history_file(str(history))
|
||||
atexit.register(readline.write_history_file, str(history))
|
||||
|
||||
|
||||
atexit.register(partial(write_history, readline, history_file))
|
||||
if is_vanilla():
|
||||
setup_history()
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
import atexit
|
||||
import os
|
||||
import readline
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
from types import ModuleType
|
||||
|
||||
cache_xdg_dir = Path(
|
||||
os.environ.get("XDG_CACHE_HOME", str(Path("~/.cache").expanduser()))
|
||||
)
|
||||
cache_xdg_dir.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
history_file = cache_xdg_dir.joinpath("python_history")
|
||||
history_file.touch()
|
||||
|
||||
readline.read_history_file(history_file)
|
||||
|
||||
|
||||
def write_history(readline: ModuleType, history_file: Path) -> None:
|
||||
"""
|
||||
We need to get ``readline`` and ``history_file`` as arguments, as it
|
||||
seems they get garbage collected when the function is registered and
|
||||
the program ends, even though we refer to them here.
|
||||
"""
|
||||
readline.write_history_file(history_file)
|
||||
|
||||
|
||||
atexit.register(partial(write_history, readline, history_file))
|
844
home/.config/qalculate/qalculate-gtk.cfg
Normal file
844
home/.config/qalculate/qalculate-gtk.cfg
Normal file
|
@ -0,0 +1,844 @@
|
|||
|
||||
[General]
|
||||
version=5.0.1
|
||||
allow_multiple_instances=-1
|
||||
width=800
|
||||
always_on_top=0
|
||||
enable_tooltips=1
|
||||
keep_function_dialog_open=0
|
||||
error_info_shown=1
|
||||
save_mode_on_exit=1
|
||||
save_definitions_on_exit=1
|
||||
clear_history_on_exit=0
|
||||
save_history_separately=0
|
||||
history_expression_type=2
|
||||
ignore_locale=0
|
||||
load_global_definitions=1
|
||||
auto_update_exchange_rates=-1
|
||||
local_currency_conversion=1
|
||||
use_binary_prefixes=0
|
||||
check_version=0
|
||||
show_keypad=1
|
||||
show_history=0
|
||||
history_height=318
|
||||
minimal_width=500
|
||||
show_stack=1
|
||||
show_convert=0
|
||||
persistent_keypad=0
|
||||
minimal_mode=0
|
||||
show_bases_keypad=1
|
||||
continuous_conversion=1
|
||||
set_missing_prefixes=0
|
||||
rpn_keys=1
|
||||
display_expression_status=1
|
||||
parsed_expression_in_resultview=0
|
||||
enable_completion=1
|
||||
enable_completion2=1
|
||||
completion_min=1
|
||||
completion_min2=1
|
||||
completion_delay=0
|
||||
calculate_as_you_type_history_delay=2000
|
||||
use_unicode_signs=1
|
||||
lower_case_numbers=0
|
||||
duodecimal_symbols=0
|
||||
exp_display=3
|
||||
imaginary_j=0
|
||||
base_display=1
|
||||
twos_complement=1
|
||||
hexadecimal_twos_complement=0
|
||||
twos_complement_input=0
|
||||
hexadecimal_twos_complement_input=0
|
||||
programming_outbase=10
|
||||
programming_inbase=10
|
||||
spell_out_logical_operators=1
|
||||
caret_as_xor=0
|
||||
close_with_esc=-1
|
||||
digit_grouping=1
|
||||
copy_ascii=0
|
||||
copy_ascii_without_units=0
|
||||
decimal_comma=-1
|
||||
dot_as_separator=-1
|
||||
comma_as_separator=0
|
||||
gtk_theme=1
|
||||
vertical_button_padding=-1
|
||||
horizontal_button_padding=-1
|
||||
use_custom_result_font=0
|
||||
use_custom_expression_font=0
|
||||
use_custom_status_font=0
|
||||
use_custom_keypad_font=0
|
||||
use_custom_history_font=0
|
||||
use_custom_application_font=0
|
||||
multiplication_sign=2
|
||||
division_sign=1
|
||||
automatic_number_fraction_format=1
|
||||
expression_history=95czk
|
||||
expression_history=135czk
|
||||
expression_history=127czk
|
||||
expression_history=127
|
||||
expression_history=comb(30,2)×comb(25,2)×comb(20,1)
|
||||
expression_history=8!/(5!×3!)×8
|
||||
expression_history=comb(8, 3)×8
|
||||
expression_history=comb(8, 3)
|
||||
expression_history=4!×2
|
||||
expression_history=9×9×8×7×6×5
|
||||
expression_history=6!
|
||||
expression_history=2520/7!
|
||||
expression_history=7!
|
||||
expression_history=comb(45, 2)
|
||||
expression_history=(comb(64, 3))−comb(8,3)×8
|
||||
expression_history=(comb(64, 3))−comb(8,3)
|
||||
expression_history=(comb(64, 3))
|
||||
expression_history=(comb(56, 2)×comb(8, 1))×(comb(56, 1)×comb(8, 2))
|
||||
expression_history=(comb(56, 2)×comb(8, 1))+(comb(56, 1)×comb(8, 2))
|
||||
expression_history=comb(32, 2)×comb(32, 1)×2
|
||||
expression_history=4!×3!×2!×3!
|
||||
expression_history=8!
|
||||
expression_history=5×4
|
||||
expression_history=5×4×3
|
||||
expression_history=3!×3×2×2
|
||||
expression_history=5!×2
|
||||
expression_history=4!
|
||||
expression_history=4!×2×2
|
||||
expression_history=(5!)×2
|
||||
expression_history=5!
|
||||
expression_history=6×5×4×3×2×1
|
||||
expression_history=6×5×4×6×2×1
|
||||
expression_history=10!/(8!)
|
||||
expression_history=comb(8, 2)×comb(10, 4)+comb(8, 1)×comb(10, 5)+comb(10, 6)
|
||||
expression_history=comb(10,2)×comb(8,4)
|
||||
expression_history=comb(10,2)+comb(8,4)
|
||||
expression_history=comb(10,2)+comb(16,4)
|
||||
expression_history=10×9×16×15×14×13
|
||||
expression_history=4×4×3×2
|
||||
expression_history=3×4×3×2
|
||||
expression_history=3×4×3
|
||||
expression_history=2×4×3×2
|
||||
expression_history=2×4×3×2×1
|
||||
expression_history=comb(8, 2)
|
||||
expression_history=8C2
|
||||
expression_history=8×7
|
||||
expression_history=10!/(5!×5!)
|
||||
expression_history=10!/5!
|
||||
expression_history=7!/((7−5)!×5!)
|
||||
expression_history=8!/((8−5)!×5!)
|
||||
expression_history=8!/((8−5)!)
|
||||
expression_history=8!/(8−5)!
|
||||
expression_history=8×7×6
|
||||
expression_history=4!×3!
|
||||
expression_history=1726697223328−60×15×1000
|
||||
expression_history=1726697223448−60×2
|
||||
expression_history=500/280
|
||||
expression_history=498/280
|
||||
expression_history=480×2
|
||||
expression_history=1280−480
|
||||
expression_history=((86400000/1000)/60)/60
|
||||
expression_history=(86400000/1000)/60
|
||||
expression_history=86400000/1000
|
||||
expression_history=34.8usd
|
||||
expression_history=50−15
|
||||
expression_history=22usd
|
||||
expression_history=180/20
|
||||
expression_history=log2(652618)
|
||||
expression_history=652618
|
||||
expression_history=bin(652618)
|
||||
expression_history=14500/4
|
||||
expression_history=80/8
|
||||
expression_history=324×25
|
||||
expression_history=300×25
|
||||
expression_history=638/7
|
||||
expression_history=2××7
|
||||
expression_history=(15000×300)/3.6
|
||||
expression_history=15000×300
|
||||
expression_history=250czk
|
||||
expression_history=5000czk
|
||||
expression_history=5czk
|
||||
expression_history=5k
|
||||
expression_history=1504.32/60
|
||||
expression_history=1504.32czk/60eur
|
||||
expression_history=30eur/1504.32czk
|
||||
expression_history=183.75czk
|
||||
expression_history=735/4
|
||||
expression_history=(3688czk)−3625czk
|
||||
expression_history=(3688czk)−3625
|
||||
expression_history=3688czk
|
||||
expression_history=14500czk/4
|
||||
expression_history=14500czk
|
||||
expression_history=184czk
|
||||
expression_history=735czk/4
|
||||
expression_history=735czk
|
||||
expression_history=35000czk
|
||||
expression_history=20000czk
|
||||
expression_history=29×3
|
||||
expression_history=(60×20)/60
|
||||
expression_history=60×20
|
||||
history_time=1727342283
|
||||
history_expression=95czk
|
||||
history_parse=95 CZK to EUR
|
||||
history_result_approximate=€3.781 395 534
|
||||
history_time=1727342267
|
||||
history_expression=135czk
|
||||
history_parse=135 CZK to EUR
|
||||
history_result_approximate=€5.373 562 075
|
||||
history_time=1727342265
|
||||
history_expression=127czk
|
||||
history_parse=127 CZK to EUR
|
||||
history_result_approximate=€5.055 128 766
|
||||
history_time=1727342263
|
||||
history_expression=127
|
||||
history_parse=127
|
||||
history_result=127
|
||||
history_time=1727342256
|
||||
history_expression=135czk
|
||||
history_parse=135 CZK
|
||||
history_result_approximate=$6.015 165 386
|
||||
history_time=1727342258
|
||||
history_result_approximate=CVE 592.542 690 0
|
||||
history_result_approximate=537.356 207 5 eurocents
|
||||
history_time=1727342259
|
||||
history_result_approximate=€5.373 562 075
|
||||
history_time=1727292570
|
||||
history_expression=comb(30,2)×comb(25,2)×comb(20,1)
|
||||
history_parse=comb(30, 2) × comb(25, 2) × comb(20, 1)
|
||||
history_result=2 610 000
|
||||
history_time=1727292525
|
||||
history_expression=8!/(5!×3!)×8
|
||||
history_parse=(factorial(8) ∕ (factorial(5) × factorial(3))) × 8
|
||||
history_result=448
|
||||
history_time=1727292493
|
||||
history_expression=comb(8, 3)×8
|
||||
history_parse=comb(8, 3) × 8
|
||||
history_result=448
|
||||
history_time=1727292489
|
||||
history_expression=comb(8, 3)
|
||||
history_parse=comb(8, 3)
|
||||
history_result=56
|
||||
history_time=1727292470
|
||||
history_expression=4!×2
|
||||
history_parse=factorial(4) × 2
|
||||
history_result=48
|
||||
history_time=1727292259
|
||||
history_expression=9×9×8×7×6×5
|
||||
history_parse=9 × 9 × 8 × 7 × 6 × 5
|
||||
history_result=136 080
|
||||
history_time=1727292219
|
||||
history_expression=6!
|
||||
history_parse=factorial(6)
|
||||
history_result=720
|
||||
history_time=1727281361
|
||||
history_expression=2520/7!
|
||||
history_parse=2520 ∕ factorial(7)
|
||||
history_result=0.5
|
||||
history_time=1727281337
|
||||
history_expression=7!
|
||||
history_parse=factorial(7)
|
||||
history_result=5040
|
||||
history_time=1727280771
|
||||
history_expression=comb(45, 2)
|
||||
history_parse=comb(45, 2)
|
||||
history_result=990
|
||||
history_time=1727280717
|
||||
history_expression=(comb(64, 3))−comb(8,3)×8
|
||||
history_parse=comb(64, 3) − (comb(8, 3) × 8)
|
||||
history_result=41 216
|
||||
history_time=1727280688
|
||||
history_expression=(comb(64, 3))−comb(8,3)
|
||||
history_parse=comb(64, 3) − comb(8, 3)
|
||||
history_result=41 608
|
||||
history_time=1727280639
|
||||
history_expression=(comb(64, 3))
|
||||
history_parse=comb(64, 3)
|
||||
history_result=41 664
|
||||
history_time=1727280572
|
||||
history_expression=(comb(56, 2)×comb(8, 1))×(comb(56, 1)×comb(8, 2))
|
||||
history_parse=(comb(56, 2) × comb(8, 1)) × (comb(56, 1) × comb(8, 2))
|
||||
history_result=19 317 760
|
||||
history_time=1727280500
|
||||
history_expression=(comb(56, 2)×comb(8, 1))+(comb(56, 1)×comb(8, 2))
|
||||
history_parse=(comb(56, 2) × comb(8, 1)) + (comb(56, 1) × comb(8, 2))
|
||||
history_result=13 888
|
||||
history_time=1727280492
|
||||
history_expression=(comb(56, 2)×comb(8, 1))×(comb(56, 1)×comb(8, 2))
|
||||
history_parse=(comb(56, 2) × comb(8, 1)) × (comb(56, 1) × comb(8, 2))
|
||||
history_result=19 317 760
|
||||
history_time=1727280408
|
||||
history_expression=comb(32, 2)×comb(32, 1)×2
|
||||
history_parse=comb(32, 2) × comb(32, 1) × 2
|
||||
history_result=31 744
|
||||
history_time=1727280364
|
||||
history_expression=4!×3!×2!×3!
|
||||
history_parse=factorial(4) × factorial(3) × factorial(2) × factorial(3)
|
||||
history_result=1728
|
||||
history_time=1727280317
|
||||
history_expression=8!
|
||||
history_parse=factorial(8)
|
||||
history_result=40 320
|
||||
history_time=1727280292
|
||||
history_expression=5×4
|
||||
history_parse=5 × 4
|
||||
history_result=20
|
||||
history_time=1727280285
|
||||
history_expression=5×4×3
|
||||
history_parse=5 × 4 × 3
|
||||
history_result=60
|
||||
history_time=1727280190
|
||||
history_expression=3!×3×2×2
|
||||
history_parse=factorial(3) × 3 × 2 × 2
|
||||
history_result=72
|
||||
history_time=1727279907
|
||||
history_expression=5!×2
|
||||
history_parse=factorial(5) × 2
|
||||
history_result=240
|
||||
history_time=1727279831
|
||||
history_expression=4!
|
||||
history_parse=factorial(4)
|
||||
history_result=24
|
||||
history_time=1727279830
|
||||
history_expression=4!×2
|
||||
history_parse=factorial(4) × 2
|
||||
history_result=48
|
||||
history_time=1727279778
|
||||
history_expression=4!×2×2
|
||||
history_parse=factorial(4) × 2 × 2
|
||||
history_result=96
|
||||
history_time=1727279719
|
||||
history_expression=(5!)×2
|
||||
history_parse=factorial(5) × 2
|
||||
history_result=240
|
||||
history_time=1727279715
|
||||
history_expression=5!
|
||||
history_parse=factorial(5)
|
||||
history_result=120
|
||||
history_time=1727279713
|
||||
history_expression=6!
|
||||
history_parse=factorial(6)
|
||||
history_result=720
|
||||
history_time=1727279701
|
||||
history_expression=5!
|
||||
history_parse=factorial(5)
|
||||
history_result=120
|
||||
history_time=1727279632
|
||||
history_expression=6×5×4×3×2×1
|
||||
history_parse=6 × 5 × 4 × 3 × 2 × 1
|
||||
history_result=720
|
||||
history_time=1727279622
|
||||
history_expression=6×5×4×6×2×1
|
||||
history_parse=6 × 5 × 4 × 6 × 2 × 1
|
||||
history_result=1440
|
||||
history_time=1727279485
|
||||
history_expression=6×5×4×6×2×1
|
||||
history_parse=6 × 5 × 4 × 6 × 2 × 1
|
||||
history_result=1440
|
||||
history_time=1727279609
|
||||
history_result=(8 × 10<sup>29</sup> ∕ 89 009 813) × √(α) × q<sub>P</sub>
|
||||
history_time=1727279432
|
||||
history_expression=10!/(8!)
|
||||
history_parse=factorial(10) ∕ factorial(8)
|
||||
history_result=90
|
||||
history_time=1727279388
|
||||
history_expression=comb(8, 2)×comb(10, 4)+comb(8, 1)×comb(10, 5)+comb(10, 6)
|
||||
history_parse=(comb(8, 2) × comb(10, 4)) + (comb(8, 1) × comb(10, 5)) + comb(10, 6)
|
||||
history_result=8106
|
||||
history_time=1727279314
|
||||
history_expression=comb(10,2)×comb(8,4)
|
||||
history_parse=comb(10, 2) × comb(8, 4)
|
||||
history_result=3150
|
||||
history_time=1727279296
|
||||
history_expression=comb(10,2)+comb(8,4)
|
||||
history_parse=comb(10, 2) + comb(8, 4)
|
||||
history_result=115
|
||||
history_time=1727279276
|
||||
history_expression=comb(10,2)+comb(16,4)
|
||||
history_parse=comb(10, 2) + comb(16, 4)
|
||||
history_result=1865
|
||||
history_time=1727279232
|
||||
history_expression=10×9×16×15×14×13
|
||||
history_parse=10 × 9 × 16 × 15 × 14 × 13
|
||||
history_result=3 931 200
|
||||
history_time=1727279148
|
||||
history_expression=4×4×3×2
|
||||
history_parse=4 × 4 × 3 × 2
|
||||
history_result=96
|
||||
history_time=1727279136
|
||||
history_expression=3×4×3×2
|
||||
history_parse=3 × 4 × 3 × 2
|
||||
history_result=72
|
||||
history_time=1727279114
|
||||
history_expression=3×4×3
|
||||
history_parse=3 × 4 × 3
|
||||
history_result=36
|
||||
history_time=1727278893
|
||||
history_expression=2×4×3×2
|
||||
history_parse=2 × 4 × 3 × 2
|
||||
history_result=48
|
||||
history_time=1727278843
|
||||
history_expression=2×4×3×2×1
|
||||
history_parse=2 × 4 × 3 × 2 × 1
|
||||
history_result=48
|
||||
history_time=1727278684
|
||||
history_expression=comb(8, 2)
|
||||
history_parse=comb(8, 2)
|
||||
history_result=28
|
||||
history_time=1727278667
|
||||
history_expression=8C2
|
||||
history_parse=8 coulomb<sup>2</sup>
|
||||
history_result=8 C<sup>2</sup>
|
||||
history_time=1727278616
|
||||
history_expression=8×7
|
||||
history_parse=8 × 7
|
||||
history_result=56
|
||||
history_time=1727278554
|
||||
history_expression=10!/(5!×5!)
|
||||
history_parse=factorial(10) ∕ (factorial(5) × factorial(5))
|
||||
history_result=252
|
||||
history_time=1727278540
|
||||
history_expression=10!/5!
|
||||
history_parse=factorial(10) ∕ factorial(5)
|
||||
history_result=30 240
|
||||
history_time=1727278512
|
||||
history_expression=7!/((7−5)!×5!)
|
||||
history_parse=factorial(7) ∕ (factorial(7 − 5) × factorial(5))
|
||||
history_result=21
|
||||
history_time=1727278486
|
||||
history_expression=8!/((8−5)!×5!)
|
||||
history_parse=factorial(8) ∕ (factorial(8 − 5) × factorial(5))
|
||||
history_result=56
|
||||
history_time=1727278425
|
||||
history_expression=8!/(8−5)!
|
||||
history_parse=factorial(8) ∕ factorial(8 − 5)
|
||||
history_result=6720
|
||||
history_time=1727278231
|
||||
history_expression=8×7×6
|
||||
history_parse=8 × 7 × 6
|
||||
history_result=336
|
||||
history_time=1727276103
|
||||
history_expression=4!×3!
|
||||
history_parse=factorial(4) × factorial(3)
|
||||
history_result=144
|
||||
history_time=1726696097
|
||||
history_expression=1726697223328−60×15×1000
|
||||
history_parse=1 726 697 223 328 − (60 × 15 × 1000)
|
||||
history_result=1 726 696 323 328
|
||||
history_time=1726696068
|
||||
history_expression=1726697223448−60×2
|
||||
history_parse=1 726 697 223 448 − (60 × 2)
|
||||
history_result=1 726 697 223 328
|
||||
history_time=1726619113
|
||||
history_expression=500/280
|
||||
history_parse=500 ∕ 280
|
||||
history_result=25 ∕ 14
|
||||
history_time=1726619106
|
||||
history_expression=498/280
|
||||
history_parse=498 ∕ 280
|
||||
history_result=249 ∕ 140
|
||||
history_time=1726593466
|
||||
history_expression=480×2
|
||||
history_parse=480 × 2
|
||||
history_result=960
|
||||
history_time=1726592811
|
||||
history_expression=1280−480
|
||||
history_parse=1280 − 480
|
||||
history_result=800
|
||||
history_time=1726523587
|
||||
history_expression=((86400000/1000)/60)/60
|
||||
history_parse=((86 400 000 ∕ 1000) ∕ 60) ∕ 60
|
||||
history_result=24
|
||||
history_time=1726523579
|
||||
history_expression=(86400000/1000)/60
|
||||
history_parse=(86 400 000 ∕ 1000) ∕ 60
|
||||
history_result=1440
|
||||
history_time=1726523576
|
||||
history_expression=86400000/1000
|
||||
history_parse=86 400 000 ∕ 1000
|
||||
history_result=86 400
|
||||
history_time=1726496554
|
||||
history_expression=34.8usd
|
||||
history_parse=34.8 USD
|
||||
history_result=$34.8
|
||||
history_time=1726496555
|
||||
history_result_approximate=CVE 3449.034 694
|
||||
history_result_approximate=3127.808 736 eurocents
|
||||
history_time=1726496556
|
||||
history_result_approximate=€31.278 087 36
|
||||
history_time=1726234180
|
||||
history_expression=50−15
|
||||
history_parse=50 − 15
|
||||
history_result=35
|
||||
history_time=1726162266
|
||||
history_expression=22usd
|
||||
history_parse=22 USD
|
||||
history_result=$22
|
||||
history_time=1726162273
|
||||
history_result_approximate=CVE 2202.196 805
|
||||
history_result_approximate=1997.095 134 eurocents
|
||||
history_time=1726162274
|
||||
history_result_approximate=€19.970 951 34
|
||||
history_time=1726060907
|
||||
history_expression=180/20
|
||||
history_parse=180 ∕ 20
|
||||
history_result=9
|
||||
history_time=1726046557
|
||||
history_expression=log2(652618)
|
||||
history_parse=log<sub>2</sub>(652 618)
|
||||
history_result_approximate=19.315 879 25
|
||||
history_time=1726046521
|
||||
history_expression=652618
|
||||
history_parse=652 618
|
||||
history_result=652 618
|
||||
history_time=1726046530
|
||||
history_result=0000 0000 0000 1001 1111 0101 0100 1010<sub><small>2</small></sub>
|
||||
history_time=1726046551
|
||||
history_result=652 618
|
||||
history_time=1726046517
|
||||
history_expression=bin(652618)
|
||||
history_parse=bin(<i>"652618"</i>)
|
||||
history_error=Character '6' was ignored in the number "652618" with base 2.
|
||||
history_error=Character '5' was ignored in the number "652618" with base 2.
|
||||
history_error=Character '2' was ignored in the number "652618" with base 2.
|
||||
history_error=Character '8' was ignored in the number "652618" with base 2.
|
||||
history_result=1
|
||||
history_time=1726046512
|
||||
history_expression=652618
|
||||
history_parse=652 618
|
||||
history_result=652 618
|
||||
history_time=1725978858
|
||||
history_expression=14500/4
|
||||
history_parse=14 500 ∕ 4
|
||||
history_result=3625
|
||||
history_time=1725574098
|
||||
history_expression=80/8
|
||||
history_parse=80 ∕ 8
|
||||
history_result=10
|
||||
history_time=1725463240
|
||||
history_expression=324×25
|
||||
history_parse=324 × 25
|
||||
history_result=8100
|
||||
history_time=1725463233
|
||||
history_expression=300×25
|
||||
history_parse=300 × 25
|
||||
history_result=7500
|
||||
history_time=1725105187
|
||||
history_expression=638/7
|
||||
history_parse=638 ∕ 7
|
||||
history_result_approximate=91.142 857 14
|
||||
history_time=1725104792
|
||||
history_expression=2××7
|
||||
history_parse=2<sup>7</sup>
|
||||
history_result=128
|
||||
history_time=1724192718
|
||||
history_expression=(15000×300)/3.6
|
||||
history_parse=(15 000 × 300) ∕ 3.6
|
||||
history_result=1 250 000
|
||||
history_time=1724192715
|
||||
history_expression=15000×300
|
||||
history_parse=15 000 × 300
|
||||
history_result=4 500 000
|
||||
history_time=1724173179
|
||||
history_expression=250czk
|
||||
history_parse=250 CZK
|
||||
history_result_approximate=$11.014 389 06
|
||||
history_time=1724173180
|
||||
history_result_approximate=CVE 1095.774 704
|
||||
history_result_approximate=993.719 691 5 eurocents
|
||||
history_time=1724173181
|
||||
history_result_approximate=€9.937 196 915
|
||||
history_time=1724172274
|
||||
history_expression=5000czk
|
||||
history_parse=5000 CZK
|
||||
history_result_approximate=$220.287 781 2
|
||||
history_time=1724172276
|
||||
history_result_approximate=CDF 630 288.4268
|
||||
history_time=1724172277
|
||||
history_result_approximate=CVE 21 915.494 08
|
||||
history_result_approximate=19 874.393 83 eurocents
|
||||
history_time=1724172278
|
||||
history_result_approximate=€198.743 938 3
|
||||
history_time=1724172270
|
||||
history_expression=5czk
|
||||
history_parse=5 CZK
|
||||
history_result_approximate=$0.220 287 781 2
|
||||
history_time=1724172207
|
||||
history_expression=5k
|
||||
history_parse=5 × 1000
|
||||
history_result=5000
|
||||
history_time=1724171979
|
||||
history_expression=1504.32/60
|
||||
history_parse=1504.32 ∕ 60
|
||||
history_result=25.072
|
||||
history_time=1724171974
|
||||
history_expression=1504.32czk/60eur
|
||||
history_parse=(1504.32 CZK) ∕ (60 EUR)
|
||||
history_result_approximate=0.996 581 604 3
|
||||
history_time=1724171966
|
||||
history_expression=30eur/1504.32czk
|
||||
history_parse=(30 EUR) ∕ (1504.32 CZK)
|
||||
history_result_approximate=0.501 715 060 6
|
||||
history_time=1724171791
|
||||
history_expression=5000czk
|
||||
history_parse=5000 CZK
|
||||
history_result_approximate=$220.287 781 2
|
||||
history_time=1724167931
|
||||
history_expression=183.75czk
|
||||
history_parse=183.75 CZK
|
||||
history_result_approximate=$8.095 575 960
|
||||
history_time=1724167933
|
||||
history_result_approximate=CVE 805.394 407 3
|
||||
history_result_approximate=730.383 973 3 eurocents
|
||||
history_time=1724167935
|
||||
history_result_approximate=€7.303 839 733
|
||||
history_time=1724167917
|
||||
history_expression=735/4
|
||||
history_parse=735 ∕ 4
|
||||
history_result=183.75
|
||||
history_time=1724167611
|
||||
history_expression=(3688czk)−3625czk
|
||||
history_parse=(3688 CZK) − (3625 CZK) to EUR
|
||||
history_result_approximate=€2.504 173 623
|
||||
history_time=1724167609
|
||||
history_expression=(3688czk)−3625
|
||||
history_parse=(3688 CZK) − 3625 to EUR
|
||||
history_result_approximate=€146.593 528 9 − 3625.000 000
|
||||
history_time=1724167603
|
||||
history_expression=3688czk
|
||||
history_parse=3688 CZK to EUR
|
||||
history_result_approximate=€146.593 528 9
|
||||
history_time=1724167540
|
||||
history_expression=14500czk/4
|
||||
history_parse=(14 500 CZK) ∕ 4 to EUR
|
||||
history_result_approximate=€144.089 355 3
|
||||
history_time=1724167532
|
||||
history_expression=14500czk
|
||||
history_parse=14 500 CZK
|
||||
history_result_approximate=$638.834 565 5
|
||||
history_time=1724167534
|
||||
history_result_approximate=CVE 63 554.932 82
|
||||
history_result_approximate=57 635.742 11 eurocents
|
||||
history_time=1724167535
|
||||
history_result_approximate=€576.357 421 1
|
||||
history_time=1724167230
|
||||
history_expression=183.75czk
|
||||
history_parse=183.75 CZK
|
||||
history_result_approximate=$8.095 575 960
|
||||
history_time=1724167237
|
||||
history_result_approximate=CVE 805.394 407 3
|
||||
history_result_approximate=730.383 973 3 eurocents
|
||||
history_time=1724167238
|
||||
history_result_approximate=€7.303 839 733
|
||||
history_time=1724167225
|
||||
history_expression=735/4
|
||||
history_parse=735 ∕ 4
|
||||
history_result=183.75
|
||||
history_time=1724167222
|
||||
history_expression=184czk
|
||||
history_parse=184 CZK
|
||||
history_result_approximate=$8.106 590 349
|
||||
history_time=1724167207
|
||||
history_expression=735/4
|
||||
history_parse=735 ∕ 4
|
||||
history_result=183.75
|
||||
history_time=1724167172
|
||||
history_expression=735czk/4
|
||||
history_parse=(735 CZK) ∕ 4
|
||||
history_result_approximate=$8.095 575 960
|
||||
history_time=1724167168
|
||||
history_expression=735czk
|
||||
history_parse=735 CZK
|
||||
history_result_approximate=$32.382 303 84
|
||||
history_time=1724166888
|
||||
history_expression=14500/4
|
||||
history_parse=14 500 ∕ 4
|
||||
history_result=3625
|
||||
history_time=1724080135
|
||||
history_expression=35000czk
|
||||
history_parse=35 000 CZK
|
||||
history_result_approximate=$1534.629 284
|
||||
history_time=1724080106
|
||||
history_expression=20000czk
|
||||
history_parse=20 000 CZK
|
||||
history_result_approximate=$876.931 019 4
|
||||
history_time=1724013854
|
||||
history_expression=29×3
|
||||
history_parse=29 × 3
|
||||
history_result=87
|
||||
history_time=1724013476
|
||||
history_expression=(60×20)/60
|
||||
history_parse=(60 × 20) ∕ 60
|
||||
history_result=20
|
||||
history_time=1724013473
|
||||
history_expression=60×20
|
||||
history_parse=60 × 20
|
||||
history_result=1200
|
||||
history_time=1724013442
|
||||
history_expression=24+24+12
|
||||
history_parse=24 + 24 + 12
|
||||
history_result=60
|
||||
history_time=1723541887
|
||||
history_expression=38+15
|
||||
history_parse=38 + 15
|
||||
history_result=53
|
||||
history_time=1723541880
|
||||
history_expression=(43−33)+5
|
||||
history_parse=(43 − 33) + 5
|
||||
history_result=15
|
||||
history_time=1723541879
|
||||
history_expression=43−33
|
||||
history_parse=43 − 33
|
||||
history_result=10
|
||||
history_time=1723319641
|
||||
history_expression=11mA×1kohm
|
||||
history_parse=(11 milliamperes) × (1 kiloohm)
|
||||
history_result=11 V
|
||||
history_time=1723319554
|
||||
history_expression=220ohm×54mA
|
||||
history_parse=(220 ohms) × (54 milliamperes)
|
||||
history_result=11.88 V
|
||||
history_time=1723317250
|
||||
history_expression=1.5k×7mA
|
||||
history_parse=(1.5 × 1000) × (7 milliamperes)
|
||||
history_result=10.5 A
|
||||
history_time=1723317195
|
||||
history_expression=12.5V/5mA
|
||||
history_parse=(12.5 volts) ∕ (5 milliamperes)
|
||||
history_result=2.5 kΩ
|
||||
history_time=1723317115
|
||||
history_expression=11k×7×10^−3
|
||||
history_parse=(11 × 1000) × 7 × 10<sup>−3</sup>
|
||||
history_result=77
|
||||
history_time=1723317084
|
||||
history_expression=11k×7m
|
||||
history_parse=(11 × 1000) × (7 meters)
|
||||
history_result=77 km
|
||||
history_time=1723317016
|
||||
history_expression=12/(1×10^−3)
|
||||
history_parse=12 ∕ (1 × 10<sup>−3</sup>)
|
||||
history_result=12 000
|
||||
history_time=1723316369
|
||||
history_expression=12V/200ohm
|
||||
history_parse=(12 volts) ∕ (200 ohms)
|
||||
history_result=60 mA
|
||||
history_time=1723316359
|
||||
history_expression=12v/200ohm
|
||||
history_parse=12 ∕ (200 ohms)
|
||||
history_error=Trailing characters "v" (not a valid variable/function/unit) in number "12v" were ignored.
|
||||
history_result=60 mS
|
||||
history_time=1723232596
|
||||
history_expression=190ml/8.3s
|
||||
history_parse=(190 milliliters) ∕ (8.3 seconds)
|
||||
history_result_approximate=22.891 566 27 mL ∕ s
|
||||
history_time=1723059809
|
||||
history_expression=(10800/60)/60
|
||||
history_parse=(10 800 ∕ 60) ∕ 60
|
||||
history_result=3
|
||||
history_time=1723059807
|
||||
history_expression=10800/60
|
||||
history_parse=10 800 ∕ 60
|
||||
history_result=180
|
||||
history_time=1722970501
|
||||
history_expression=0.98××30
|
||||
history_parse=0.98<sup>30</sup>
|
||||
history_result_approximate=0.545 484 319 4
|
||||
history_time=1722855354
|
||||
history_expression=10cad
|
||||
history_parse=10 CAD to EUR
|
||||
history_result_approximate=€6.651 147 323
|
||||
history_time=1722855343
|
||||
history_expression=10×52
|
||||
history_parse=10 × 52
|
||||
history_result=520
|
||||
history_time=1722855320
|
||||
history_expression=43×52
|
||||
history_parse=43 × 52
|
||||
history_result=2236
|
||||
history_time=1722855280
|
||||
history_expression=65.7cad
|
||||
history_parse=65.7 CAD
|
||||
history_result_approximate=$47.346 824 08
|
||||
history_time=1722855292
|
||||
history_result_approximate=CVE 4818.582 640
|
||||
history_time=1722855293
|
||||
history_result_approximate=4369.803 791 eurocents
|
||||
history_time=1722855294
|
||||
history_result_approximate=€43.698 037 91
|
||||
history_time=1722855269
|
||||
history_expression=42.85+22.85
|
||||
history_parse=42.85 + 22.85
|
||||
history_result=65.7
|
||||
recent_functions=
|
||||
recent_variables=
|
||||
recent_units=
|
||||
latest_button_currency=USD
|
||||
|
||||
[Mode]
|
||||
min_deci=0
|
||||
use_min_deci=0
|
||||
max_deci=2
|
||||
use_max_deci=0
|
||||
precision=10
|
||||
interval_arithmetic=1
|
||||
interval_display=0
|
||||
min_exp=-1
|
||||
negative_exponents=0
|
||||
sort_minus_last=1
|
||||
number_fraction_format=1
|
||||
complex_number_form=0
|
||||
use_prefixes=1
|
||||
use_prefixes_for_all_units=0
|
||||
use_prefixes_for_currencies=0
|
||||
abbreviate_names=1
|
||||
all_prefixes_enabled=0
|
||||
denominator_prefix_enabled=1
|
||||
place_units_separately=1
|
||||
auto_post_conversion=3
|
||||
mixed_units_conversion=3
|
||||
number_base=10
|
||||
number_base_expression=10
|
||||
read_precision=0
|
||||
assume_denominators_nonzero=1
|
||||
warn_about_denominators_assumed_nonzero=1
|
||||
structuring=1
|
||||
angle_unit=1
|
||||
functions_enabled=1
|
||||
variables_enabled=1
|
||||
calculate_functions=1
|
||||
calculate_variables=1
|
||||
variable_units_enabled=1
|
||||
sync_units=1
|
||||
unknownvariables_enabled=0
|
||||
units_enabled=1
|
||||
allow_complex=1
|
||||
allow_infinite=1
|
||||
indicate_infinite_series=0
|
||||
show_ending_zeroes=1
|
||||
rounding_mode=0
|
||||
approximation=0
|
||||
interval_calculation=1
|
||||
concise_uncertainty_input=0
|
||||
calculate_as_you_type=0
|
||||
in_rpn_mode=0
|
||||
chain_mode=0
|
||||
limit_implicit_multiplication=0
|
||||
parsing_mode=0
|
||||
simplified_percentage=1
|
||||
implicit_question_asked=1
|
||||
spacious=1
|
||||
excessive_parenthesis=0
|
||||
visible_keypad=0
|
||||
short_multiplication=1
|
||||
default_assumption_type=4
|
||||
default_assumption_sign=0
|
||||
|
||||
[Plotting]
|
||||
plot_legend_placement=2
|
||||
plot_style=0
|
||||
plot_smoothing=0
|
||||
plot_display_grid=1
|
||||
plot_full_border=0
|
||||
plot_min=0
|
||||
plot_max=10
|
||||
plot_step=1
|
||||
plot_sampling_rate=1001
|
||||
plot_use_sampling_rate=1
|
||||
plot_variable=x
|
||||
plot_rows=0
|
||||
plot_type=0
|
||||
plot_color=1
|
||||
plot_linewidth=2
|
62
home/.config/qimgv/qimgv.conf
Normal file
62
home/.config/qimgv/qimgv.conf
Normal file
|
@ -0,0 +1,62 @@
|
|||
[General]
|
||||
JPEGSaveQuality=95
|
||||
absoluteZoomStep=false
|
||||
autoResizeLimit=90
|
||||
autoResizeWindow=false
|
||||
backgroundOpacity=1
|
||||
blurBackground=false
|
||||
confirmDelete=true
|
||||
confirmTrash=false
|
||||
cursorAutohiding=true
|
||||
defaultCropAction=0
|
||||
defaultFitMode=0
|
||||
defaultViewMode=0
|
||||
drawTransparencyGrid=false
|
||||
enableSmoothScroll=true
|
||||
expandImage=false
|
||||
expandLimit=2
|
||||
firstRun=false
|
||||
focusPointIn1to1Mode=1
|
||||
folderEndAction=0
|
||||
imageScrolling=1
|
||||
infoBarFullscreen=true
|
||||
infoBarWindowed=false
|
||||
jxlAnimation=false
|
||||
keepFitMode=false
|
||||
lastVerMajor=1
|
||||
lastVerMicro=2
|
||||
lastVerMinor=0
|
||||
loopSlideshow=false
|
||||
mpvBinary=/nix/store/sz3h6s8p2r22v76m0yr6fn3m663sms7r-mpv-with-scripts-0.37.0/bin/mpv
|
||||
openInFullscreen=false
|
||||
panelEnabled=true
|
||||
panelFullscreenOnly=true
|
||||
panelPosition=top
|
||||
panelPreviewsSize=140
|
||||
playVideoSounds=false
|
||||
scalingFilter=1
|
||||
showSaveOverlay=true
|
||||
slideshowInterval=3000
|
||||
smoothAnimatedImages=true
|
||||
smoothUpscaling=true
|
||||
sortingMode=0
|
||||
squareThumbnails=false
|
||||
thumbPanelStyle=1
|
||||
thumbnailCache=true
|
||||
thumbnailerThreads=4
|
||||
unloadThumbs=true
|
||||
useOpenGL=false
|
||||
usePreloader=true
|
||||
useSystemColorScheme=false
|
||||
videoPlayback=true
|
||||
windowTitleExtendedInfo=true
|
||||
zoomIndicatorMode=0
|
||||
zoomStep=0.20000000298023224
|
||||
|
||||
[Controls]
|
||||
shortcuts="zoomIn=+", "frameStepBack=,", "zoomOut=-", "frameStep=.", "fitWindow=1", "scrollDown=2", "fitNormal=3", "scrollLeft=4", "scrollRight=6", "scrollUp=8", "exit=Alt+X", "folderView=Backspace", "crop=C", "copyFileClipboard=Ctrl+C", "showInDirectory=Ctrl+D", "zoomOut=Ctrl+Down", "rotateLeft=Ctrl+L", "seekVideoBackward=Ctrl+Left", "open=Ctrl+O", "print=Ctrl+P", "exit=Ctrl+Q", "rotateRight=Ctrl+R", "seekVideoForward=Ctrl+Right", "save=Ctrl+S", "copyPathClipboard=Ctrl+Shift+C", "saveAs=Ctrl+Shift+S", "zoomIn=Ctrl+Up", "pasteFile=Ctrl+V", "zoomOutCursor=Ctrl+WheelDown", "zoomInCursor=Ctrl+WheelUp", "discardEdits=Ctrl+Z", "s:trash with trash-cli=Del", "scrollDown=Down", "jumpToLast=End", "folderView=Enter", "closeFullScreenOrExit=Esc", "toggleFullscreen=F", "toggleFullscreen=F11", "renameFile=F2", "reloadImage=F5", "flipH=H", "jumpToFirst=Home", "toggleImageInfo=I", "toggleFullscreen=LMB_DoubleClick", "prevImage=Left", "moveFile=M", "contextMenu=Menu", "openSettings=P", "resize=R", "contextMenu=RMB", "nextImage=Right", "removeFile=Shift+Del", "toggleFullscreenInfoBar=Shift+F", "prevDirectory=Shift+Left", "nextDirectory=Shift+Right", "toggleFitMode=Space", "scrollUp=Up", "flipV=V", "nextImage=WheelDown", "prevImage=WheelUp", "prevImage=XButton1", "nextImage=XButton2", "toggleSlideshow=`", "toggleShuffle=~"
|
||||
|
||||
[Scripts]
|
||||
script\1\name=trash with trash-cli
|
||||
script\1\value=@Variant(\0\0\0\x7f\0\0\0\aScript\0\0\0\0 \0t\0r\0\x61\0s\0h\0-\0p\0u\0t\0 \0%\0\x66\0i\0l\0\x65\0%\x1)
|
||||
script\size=1
|
13
home/.config/qimgv/theme.conf
Normal file
13
home/.config/qimgv/theme.conf
Normal file
|
@ -0,0 +1,13 @@
|
|||
[Colors]
|
||||
accent=#8c9b81
|
||||
background=#1a1a1a
|
||||
background_fullscreen=#1a1a1a
|
||||
folderview=#242424
|
||||
folderview_topbar=#383838
|
||||
icons=#a4a4a4
|
||||
overlay=#1a1a1a
|
||||
overlay_text=#d2d2d2
|
||||
scrollbar=#5a5a5a
|
||||
text=#b6b6b6
|
||||
widget=#252525
|
||||
widget_border=#2c2c2c
|
|
@ -1,32 +1,2 @@
|
|||
[Appearance]
|
||||
color_scheme_path=/usr/share/qt5ct/colors/simple.conf
|
||||
custom_palette=false
|
||||
icon_theme=Papirus-Dark
|
||||
standard_dialogs=gtk3
|
||||
style=Adwaita-Dark
|
||||
|
||||
[Fonts]
|
||||
fixed=@Variant(\0\0\0@\0\0\0\x12\0N\0o\0t\0o\0 \0S\0\x61\0n\0s@(\0\0\0\0\0\0\xff\xff\xff\xff\x5\x1\0\x32\x10)
|
||||
general=@Variant(\0\0\0@\0\0\0\x12\0N\0o\0t\0o\0 \0S\0\x61\0n\0s@(\0\0\0\0\0\0\xff\xff\xff\xff\x5\x1\0\x32\x10)
|
||||
|
||||
[Interface]
|
||||
activate_item_on_single_click=1
|
||||
buttonbox_layout=0
|
||||
cursor_flash_time=1000
|
||||
dialog_buttons_have_icons=1
|
||||
double_click_interval=400
|
||||
gui_effects=@Invalid()
|
||||
keyboard_scheme=2
|
||||
menus_have_icons=true
|
||||
show_shortcuts_in_context_menus=true
|
||||
stylesheets=@Invalid()
|
||||
toolbutton_style=4
|
||||
underline_shortcut=1
|
||||
wheel_scroll_lines=3
|
||||
|
||||
[SettingsWindow]
|
||||
geometry="@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\0\0\0\0\0\0\0\0\x5$\0\0\x3\x30\0\0\0\0\0\0\0\0\0\0\x5;\0\0\x4\x92\0\0\0\0\x2\0\0\0\a\x80\0\0\0\0\0\0\0\0\0\0\x5$\0\0\x3\x30)"
|
||||
|
||||
[Troubleshooting]
|
||||
force_raster_widgets=1
|
||||
ignored_applications=@Invalid()
|
||||
|
|
2
home/.config/qt6ct/qt6ct.conf
Normal file
2
home/.config/qt6ct/qt6ct.conf
Normal file
|
@ -0,0 +1,2 @@
|
|||
[Appearance]
|
||||
icon_theme=Papirus-Dark
|
2
home/.config/rye/config.toml
Normal file
2
home/.config/rye/config.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
[default]
|
||||
license = "GPL-3.0-or-later"
|
|
@ -59,15 +59,12 @@ fi
|
|||
|
||||
# Config access shortcuts
|
||||
alias cfzsh='vim ~/.config/zsh/.zshrc'
|
||||
alias cfprofile='vim ~/.config/zsh/.zprofile'
|
||||
alias cfprompt='vim ~/.config/zsh/rc/prompt.zsh'
|
||||
alias cfalias='vim ~/.config/shell/aliases'
|
||||
alias cffunctions='vim ~/.config/shell/functions'
|
||||
alias cfprofile='vim ~/.config/shell/profile'
|
||||
alias cfenvironment='vim ~/.config/shell/environment'
|
||||
alias cfenv='cfenvironment'
|
||||
alias cfhandlers='vim ~/.config/shell/handlers'
|
||||
alias cfprompt='vim ~/.config/shell/prompt'
|
||||
alias cfkeybinds='vim ~/.config/shell/keybinds'
|
||||
alias cftodo='vim ~/Personal/vimwiki/todo.md'
|
||||
alias cfnvim='vim ~/.config/nvim'
|
||||
alias cfvim='cfnvim'
|
||||
alias cfgit='vim ~/.config/git/config'
|
||||
|
@ -75,8 +72,6 @@ alias cfhypr='vim ~/.config/hypr'
|
|||
alias cfsway='vim ~/.config/sway/config'
|
||||
|
||||
# zoxide shortcuts
|
||||
alias cd='z' # use zoxide as the default cd command
|
||||
alias cdi='zi' # interactive mode (fzf)
|
||||
alias j='z' # for the sake of old habits from autojump
|
||||
alias ji='zi' # interactive mode (fzf)
|
||||
|
||||
|
@ -142,11 +137,6 @@ alias iptlistout='iptables -L OUTPUT -n -v --line-numbers' # OUT rules
|
|||
alias iptlistfw='iptables -L FORWARD -n -v --line-numbers' # FORWARD rules
|
||||
alias ufw-log='journalctl -f -n 100 -g ufw' # Show UFW log entries in system journal
|
||||
|
||||
# Kernel actions
|
||||
alias kernel-recompile='cd /usr/src/linux && make -j7 && make -j7 modules_install && make install'
|
||||
alias kernel-oldconfig='cd /usr/src/linux && make oldconfig'
|
||||
alias kernel-configure='cd /usr/src/linux && make menuconfig'
|
||||
|
||||
# System actions
|
||||
alias sv='systemctl'
|
||||
alias pacnew="find / -name '*.pacnew' 2>/dev/null" # Search for all new configurations after pacman update
|
||||
|
@ -281,9 +271,11 @@ if [ -x /usr/bin/dircolors ]; then
|
|||
alias egrep='egrep --color=auto'
|
||||
|
||||
alias diff='diff --color=auto'
|
||||
# shellcheck disable=SC2032
|
||||
alias ip='ip --color=auto'
|
||||
|
||||
# Take advantage of $LS_COLORS for completion as well
|
||||
# shellcheck disable=SC2296
|
||||
zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}"
|
||||
fi
|
||||
|
||||
|
@ -298,12 +290,6 @@ if [ ! "$(uname -s)" = 'Darwin' ]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
# Autogenerate python aliases
|
||||
if [ -f ~/.config/shell/py-alias ]; then
|
||||
# shellcheck source=/home/itsdrike/.config/shell/py-alias
|
||||
. "$HOME/.config/shell/py-alias"
|
||||
fi
|
||||
|
||||
# Functions
|
||||
if [ -f ~/.config/shell/functions ]; then
|
||||
# shellcheck source=/home/itsdrike/.config/shell/functions
|
||||
|
|
|
@ -8,6 +8,23 @@
|
|||
# which means the XDG definitions will be ignored anyway, and
|
||||
# defining them may break programs when root is actually logged in.
|
||||
|
||||
|
||||
# Add all folders in ~/.local/bin into PATH
|
||||
# Some window managers require this line to be in profile not in .zshenv
|
||||
if [ -d "$HOME/.local/bin" ]; then
|
||||
PATH+=":${$(find -L ~/.local/bin -type d | tr '\n' ':')%%:}"
|
||||
fi
|
||||
|
||||
if [ -d "$HOME/.local/share/npm/bin" ]; then
|
||||
PATH+=":$HOME/.local/share/npm/bin"
|
||||
fi
|
||||
|
||||
# Prepend rye shims to PATH, to have rye python executables
|
||||
# take priority over the system-wide python.
|
||||
if [ -d "${RYE_HOME:-$HOME/.rye}/shims" ]; then
|
||||
PATH="${RYE_HOME:-$HOME/.rye}/shims:$PATH"
|
||||
fi
|
||||
|
||||
# Define some variables for POSIX compatibility
|
||||
uid="$(id -u)"
|
||||
|
||||
|
@ -16,14 +33,26 @@ export EDITOR="nvim"
|
|||
export BROWSER="firefox"
|
||||
export TERMINAL="alacritty"
|
||||
export DIFFPROG="nvim -d"
|
||||
export FILEMANAGER="pcmanfm"
|
||||
export FILEMANAGER="pcmanfm-qt"
|
||||
|
||||
# XDG Standard paths
|
||||
# XDG Base Directory standard paths
|
||||
export XDG_CONFIG_HOME="$HOME/.config"
|
||||
export XDG_CACHE_HOME="$HOME/.cache"
|
||||
export XDG_DATA_HOME="$HOME/.local/share"
|
||||
export XDG_RUNTIME_DIR="/run/user/$uid"
|
||||
export XDG_STATE_HOME="$HOME/.local/state"
|
||||
export XDG_BIN_HOME="$HOME/.local/bin"
|
||||
|
||||
# XDG User directories (should match ~/.config/user-dirs.dirs)
|
||||
#export XDG_DESKTOP_DIR="$HOME/Desktop"
|
||||
export XDG_DOWNLOAD_DIR="$HOME/Downloads"
|
||||
export XDG_TEMPLATES_DIR="$XDG_DATA_HOME/templates"
|
||||
export XDG_PUBLICSHARE_DIR="$XDG_DATA_HOME/public"
|
||||
#export XDG_DOCUMENTS_DIR="$HOME/Documents"
|
||||
export XDG_MUSIC_DIR="$HOME/Media/Music"
|
||||
export XDG_PICTURES_DIR="$HOME/Media/Pictures"
|
||||
export XDG_VIDEOS_DIR="$HOME/Media/Videos"
|
||||
export XDG_SCREENSHOTS_DIR="$HOME/Media/Pictures/Screenshots"
|
||||
|
||||
# Per-Application XDG settings
|
||||
export ZDOTDIR="$XDG_CONFIG_HOME/zsh"
|
||||
|
@ -33,7 +62,7 @@ export ZSH_COMPDUMP="$ZSH_CACHE/zcompdump-$ZSH_VERSION"
|
|||
export XINITRC="$XDG_CONFIG_HOME/x11/xinitrc"
|
||||
#export XAUTHORITY="$XDG_RUNTIME_DIR/Xauthority" # This line will break some DMs.
|
||||
export LESSHISTFILE="-"
|
||||
export GTK2_RC_FILES="$XDG_CONFIG_HOME/gtk-2.0/gtkrc"
|
||||
export GTK2_RC_FILES="$XDG_CONFIG_HOME/gtk-2.0/gtkrc":"$XDG_CONFIG_HOME/gtk-2.0/gtkrc.mine"
|
||||
export WGETRC="$XDG_CONFIG_HOME/wget/wgetrc"
|
||||
export GNUPGHOME="$XDG_DATA_HOME/gnupg"
|
||||
export GOPATH="$XDG_DATA_HOME/go"
|
||||
|
@ -44,22 +73,46 @@ export _JAVA_OPTIONS="-Djava.util.prefs.userRoot=$XDG_CONFIG_HOME/java"
|
|||
export NPM_CONFIG_USERCONFIG="$XDG_CONFIG_HOME/npm/npmrc"
|
||||
export NPM_CONFIG_CACHE="$XDG_CACHE_HOME/npm"
|
||||
export NPM_CONFIG_PREFIX="$XDG_DATA_HOME/npm"
|
||||
export NPM_CONFIG_TMP="$XDG_RUNTIME_DIR/npm"
|
||||
export NUGET_PACKAGES="$XDG_CACHE_HOME/NuGetPackages"
|
||||
export PARALLEL_HOME="$XDG_CONFIG_HOME/parallel"
|
||||
export RANDFILE="$XDG_CACHE_HOME/rnd"
|
||||
export PYTHONSTARTUP="$XDG_CONFIG_HOME/python/pythonrc.py"
|
||||
export PYTHONPYCACHEPREFIX="$XDG_CACHE_HOME/python"
|
||||
export PYTHONUSERBASE="$XDG_DATA_HOME/python"
|
||||
# Less commonly used applications
|
||||
export _ZL_DATA="$XDG_DATA_HOME/zlua"
|
||||
export SQLITE_HISTORY="$XDG_DATA_HOME/sqlite_history"
|
||||
export WAKATIME_HOME="$XDG_CONFIG_HOME/wakatime"
|
||||
export IPYTHONDIR="$XDG_CONFIG_HOME/ipython"
|
||||
export PYENV_ROOT="$XDG_DATA_HOME/pyenv"
|
||||
export MYPY_CACHE_DIR="$XDG_CACHE_HOME/mypy"
|
||||
#export PYLINTHOME="$XDG_CACHE_HOME/pylint"
|
||||
#export DOCKER_CONFIG="$XDG_CONFIG_HOME/docker"
|
||||
#export CUDA_CACHE_PATH="$XDG_CACHE_HOME/nv"
|
||||
export PYLINTHOME="$XDG_CACHE_HOME/pylint"
|
||||
export DOCKER_CONFIG="$XDG_CONFIG_HOME/docker"
|
||||
export CUDA_CACHE_PATH="$XDG_CACHE_HOME/nv"
|
||||
export WINEPREFIX="$XDG_DATA_HOME/wine"
|
||||
export MPLAYERHOME="$XDG_CONFIG_HOME/mplayer"
|
||||
export ANDROID_HOME="$XDG_DATA_HOME/android"
|
||||
export M2_HOME="$XDG_DATA_HOME/m2"
|
||||
export NODE_REPL_HISTORY="$XDG_DATA_HOME/node_repl_history"
|
||||
export DOTNET_CLI_HOME="$XDG_DATA_HOME/dotnet"
|
||||
export JUPYTER_CONFIG_DIR="$XDG_CONFIG_HOME/jupyter"
|
||||
export RYE_HOME="$XDG_CONFIG_HOME/rye"
|
||||
|
||||
# Theming
|
||||
export GTK_THEME="Tokyonight-Dark"
|
||||
export GTK_USE_PORTAL=1
|
||||
|
||||
export QT_STYLE_OVERRIDE=kvantum
|
||||
export QT_QPA_PLATFORMTHEME="qt5ct"
|
||||
export QT_AUTO_SCREEN_SCALE_FACTOR="1"
|
||||
export QT_QPA_PLATFORM="wayland;xcb"
|
||||
export QT_WAYLAND_DISABLE_WINDOWDECORATION="1"
|
||||
|
||||
export XCURSOR_THEME="BreezeX-RosePine-Linux"
|
||||
export XCURSOR_SIZE="24"
|
||||
|
||||
export HYPRCURSOR_THEME="rose-pine-hyprcursor"
|
||||
export HYPRCURSOR_SIZE="24"
|
||||
|
||||
# Colorful man pages!
|
||||
# Use neovim to open man pages
|
||||
|
@ -84,12 +137,9 @@ fi
|
|||
# Other program settings
|
||||
export HISTTIMEFORMAT="%Y-%m-%d %T "
|
||||
export SUDO_ASKPASS="$HOME/.local/bin/scripts/gui/prompt/menupass"
|
||||
export PIPENV_VENV_IN_PROJECT=1 # Force pipenv to create new environments within projects ./.venv
|
||||
export XSECURELOCK_SHOW_HOSTNAME=0 # Don't show hostname in xsecurelock
|
||||
export XSECURELOCK_SHOW_DATETIME=1 # Show current date and time in xsecurelock
|
||||
export QT_QPA_PLATFORMTHEME="qt5ct" # Have QT use theme from qt5ct.
|
||||
#export QT_STYLE_OVERRIDE="gtk2" # Have QT use the gtk2 theme (needs aur/qt5-styleplugins)
|
||||
#export QSG_RENDER_LOOP=basic # Fix Stremio freezing
|
||||
export PIPENV_VENV_IN_PROJECT=1 # Force pipenv to create new environments within projects ./.venv
|
||||
export XSECURELOCK_SHOW_HOSTNAME=0 # Don't show hostname in xsecurelock
|
||||
export XSECURELOCK_SHOW_DATETIME=1 # Show current date and time in xsecurelock
|
||||
|
||||
# Remove irrelevant variables added for posix compatibility
|
||||
unset posix
|
||||
|
|
|
@ -202,8 +202,8 @@ anonymize() {
|
|||
# Reset the prompt on initial run to allow this script
|
||||
# to be ran multiple times without user having to reload
|
||||
# PS1 manually
|
||||
# shellcheck source=/home/itsdrike/.config/shell/prompt
|
||||
. "${XDG_CONFIG_DIR:-$HOME/.config}/shell/prompt"
|
||||
# shellcheck source=/home/itsdrike/.config/zsh/rc/prompt.zsh
|
||||
. "${ZDOTDIR}/rc/prompt.zsh"
|
||||
|
||||
# Regular expression to match 0-255 numbers (color)
|
||||
color_int_re='^(0+)?([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])$'
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
#!/bin/zsh
|
||||
|
||||
# User .profile definition.
|
||||
# This file is only sourced once, after login, Unlike
|
||||
# .zshrc/.bashrc, which will run whenever a new terminal
|
||||
# is opened.
|
||||
|
||||
# Add all folders in ~/.local/bin into PATH
|
||||
# Some window managers require this line to be in profile
|
||||
# not in .zshenv
|
||||
if [ -d "$HOME/.local/bin" ]; then
|
||||
PATH+=":${$(find -L ~/.local/bin -type d | tr '\n' ':')%%:}"
|
||||
fi
|
||||
|
||||
if [ -d "$HOME/.local/share/pyenv/shims" ]; then
|
||||
PATH+=":$HOME/.local/share/pyenv/shims"
|
||||
fi
|
||||
|
||||
if [ -d "$HOME/.local/share/npm/bin" ]; then
|
||||
PATH+=":$HOME/.local/share/npm/bin"
|
||||
fi
|
||||
|
||||
# Start graphical session automatically on tty1 if Hyprland or startx is available
|
||||
if [ "$(tty)" = "/dev/tty1" ] && [ "$UID" != 0 ]; then
|
||||
if command -v Hyprland >/dev/null; then
|
||||
! pidof -s Hyprland >/dev/null 2>&1 && launch-hypr
|
||||
elif command -v startx >/dev/null; then
|
||||
! pidof -s Xorg >/dev/null 2>&1 && exec startx "$XINITRC"
|
||||
fi
|
||||
fi
|
|
@ -1,196 +0,0 @@
|
|||
#!/usr/bin/env zsh
|
||||
# Simple script which automatically defines certain aliases for python,
|
||||
# which will automatically use certain python version
|
||||
# Versions are automatically obtained from $PYENV_ROOT/versions directories
|
||||
# NOTE: This assumes that all folders in this directory are valid python versions
|
||||
#
|
||||
# Assume we have these installed pyenv python versions 3.6.5, 3.6.12 and 3.10.1:
|
||||
# - Set full-version aliases: py3.6.5, py3.6.12 and py3.10.1
|
||||
# - Set py3 to 3.10.1 (latest with major version 3)
|
||||
# - Set py3.6 to 3.6.12 (latest with major version 3 and minor version 6)
|
||||
# - Set py3.10 to 3.10.1 (latest, and only python with major version 3 and minor version 10)
|
||||
|
||||
|
||||
# Define all wanted aliases for a given python version
|
||||
# $1 - full valid pyenv python version (for example '3.6.12', `3.11-dev`, or `pypy3.6-7.2.0-src`)
|
||||
# $2 - version used in the alias (for example '3.6', '3', or even '', but also `pypy3.7`, ...)
|
||||
define_aliases() {
|
||||
version="$1"
|
||||
alias_version="$2"
|
||||
cmd_prefix="PYENV_VERSION=$version"
|
||||
|
||||
alias "py$alias_version=$cmd_prefix python"
|
||||
alias "ipy$alias_version=$cmd_prefix ipython"
|
||||
alias "bpy$alias_version=$cmd_prefix bpython"
|
||||
alias "pydoc$alias_version=$cmd_prefix pydoc"
|
||||
alias "pytest$alias_version=$cmd_prefix pytest"
|
||||
alias -g "PY$alias_version=$cmd_prefix"
|
||||
}
|
||||
|
||||
# Handle splitting full version into prefix, version number and suffix
|
||||
# Because of the huge variaty of python implemenations and their different namings,
|
||||
# this function will only be able to handle the default CPython version names,
|
||||
# which follow the regex pattern of: '\d+\.\d+\.\d+', the rest will print 'full_version;;'
|
||||
# In the future, this may also include support for some other naming schemes.
|
||||
# $1 - full valid pyenv python version (for example '3.6.12', `3.11-dev`, or `pypy3.6-7.2.0-src`)
|
||||
parse_python_version() {
|
||||
full_version="$1"
|
||||
if echo "$full_version" | grep -E "[0-9]+\.[0-9]+\.[0-9]+" >/dev/null; then
|
||||
echo ";$full_version;"
|
||||
else
|
||||
echo ';;'
|
||||
fi
|
||||
}
|
||||
|
||||
# Prints version number extracted from alias for given version
|
||||
# $1 - version used in the alias (for example '3.6', '3', or even '', but also 'pypy3.6', ...)
|
||||
get_alias_version() {
|
||||
alias_version="$1"
|
||||
definition="$(alias "py$alias_version")"
|
||||
full_version="$(echo "$definition" | cut -d= -f3 | cut -d' ' -f1)"
|
||||
|
||||
version_info="$(parse_python_version "$full_version")"
|
||||
version="$(echo "$version_info" | cut -d';' -f2)"
|
||||
echo "$version"
|
||||
}
|
||||
|
||||
# Compares 2 python versions in major, minor and micro parts
|
||||
# $1 - version #1
|
||||
# $2 - version #2
|
||||
# Returns:
|
||||
# 0 - version #1 is newer
|
||||
# 1 - version #2 is newer
|
||||
# 2 - versions are equal
|
||||
version_compare() {
|
||||
version_1="$1"
|
||||
version_2="$2"
|
||||
# ZSH Only:
|
||||
version_1=("${(@s:.:)version_1}")
|
||||
version_2=("${(@s:.:)version_2}")
|
||||
major_1=$version_1[1]
|
||||
major_2=$version_2[1]
|
||||
minor_1=$version_1[2]
|
||||
minor_2=$version_2[2]
|
||||
micro_1=$version_1[3]
|
||||
micro_2=$version_2[3]
|
||||
# POSIX, but slow:
|
||||
# major_1="$(echo "$version_1" | cut -d. -f1)"
|
||||
# major_2="$(echo "$version_2" | cut -d. -f1)"
|
||||
# minor_1="$(echo "$version_1" | cut -d. -f2)"
|
||||
# minor_2="$(echo "$version_2" | cut -d. -f2)"
|
||||
# micro_1="$(echo "$version_1" | cut -d. -f3)"
|
||||
# micro_2="$(echo "$version_2" | cut -d. -f3)"
|
||||
|
||||
# Compare majors
|
||||
if [ $major_1 -gt $major_2 ]; then
|
||||
# version 1's major is bigger, version 1 is newer
|
||||
return 0
|
||||
elif [ $major_1 -lt $major_2 ]; then
|
||||
# version 1's major is smaller, version 2 is newer
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Majors equal, compare minors
|
||||
if [ $minor_1 -gt $minor_2 ]; then
|
||||
# version 1's minor is bigger, version 1 is newer
|
||||
return 0
|
||||
elif [ $minor_1 -lt $minor_2 ]; then
|
||||
# version 1's major is smaller, version 2 is newer
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Minors equal, compare micros
|
||||
if [ $micro_1 -gt $micro_2 ]; then
|
||||
# version 1's micro is bigger, version 1 is newer
|
||||
return 0
|
||||
elif [ $micro_1 -lt $micro_2 ]; then
|
||||
# version 1's micro is smaller, version 2 is newer
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Micros equal, versions equal
|
||||
return 2
|
||||
}
|
||||
|
||||
# Define new aliases if they don't already exsist, in which case override
|
||||
# if the current version is newer than the version in the alias
|
||||
# $1 - full valid pyenv python version (for example '3.6.12', `3.11-dev`, or `pypy3.6-7.2.0-src`)
|
||||
# $2 - version used in the alias (for example '3.6', '3', or even '', but also `pypy3.7`, ...)
|
||||
try_define_aliases() {
|
||||
version="$1"
|
||||
alias_version="$2"
|
||||
|
||||
# Check if alias already exists
|
||||
if alias "py$alias_version" >/dev/null; then
|
||||
# Compare version from the existing alias with current version,
|
||||
# if current is newer, override the existing alias(es)
|
||||
defined_version="$(get_alias_version "$alias_version")"
|
||||
if version_compare "$version" "$defined_version"; then
|
||||
define_aliases "$version" "$alias_version"
|
||||
# echo "Overwrote '$alias_version' aliases to point to '$version'"
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# The aliases aren't already defined, it's safe to create them
|
||||
define_aliases "$version" "$alias_version"
|
||||
# echo "Made '$alias_version' aliases pointing to '$version'"
|
||||
return 0
|
||||
}
|
||||
|
||||
define_version_aliases() {
|
||||
prefix="$1"
|
||||
version="$2"
|
||||
suffix="$3"
|
||||
|
||||
|
||||
# ZSH only:
|
||||
version_data=("${(@s:.:)version}")
|
||||
major_version=$version_data[1]
|
||||
minor_version=$version_data[2]
|
||||
# POSIX, but slow:
|
||||
# major_version="$(echo "$version" | cut -d. -f1)"
|
||||
# minor_version="$(echo "$version" | cut -d. -f2)"
|
||||
|
||||
# Define the major.minor.micro (full) alias
|
||||
try_define_aliases "$version" "$prefix$version$suffix"
|
||||
# Define the major.minor alias
|
||||
try_define_aliases "$version" "$prefix$major_version.$minor_version$suffix"
|
||||
# Define the major alias
|
||||
try_define_aliases "$version" "$prefix$major_version$suffix"
|
||||
# Define top level alias
|
||||
try_define_aliases "$version" "$prefix$suffix"
|
||||
}
|
||||
|
||||
for python_dir in "$PYENV_ROOT"/versions/*/ ; do
|
||||
full_version="$(basename $python_dir)"
|
||||
|
||||
version_info="$(parse_python_version "$full_version")"
|
||||
if [ $version_info = ';;' ]; then
|
||||
# Version info wasn't obtained successfully, skip this version
|
||||
echo "Skipped $full_version"
|
||||
continue
|
||||
fi
|
||||
|
||||
# ZSH only:
|
||||
version_data=("${(@s:;:)version_info}")
|
||||
prefix=$version_data[1]
|
||||
version=$version_data[2]
|
||||
suffix=$version_data[3]
|
||||
# POSIX, but slow:
|
||||
# prefix="$(echo "$version_info" | cut -d';' -f1)"
|
||||
# version="$(echo "$version_info" | cut -d';' -f2)"
|
||||
# suffix="$(echo "$version_info" | cut -d';' -f3)"
|
||||
|
||||
# startTime=$(date +%N)
|
||||
define_version_aliases "$prefix" "$version" "$suffix"
|
||||
# endTime=$(date +%N)
|
||||
# nanos="$(expr $endTime - $startTime)"
|
||||
# echo "took $(expr $nanos / 1000000) miliseconds"
|
||||
done
|
||||
|
||||
if command -v poetry >/dev/null 2>&1; then
|
||||
alias poetry-pyenv='poetry env use "$(pyenv which python)" && poetry install'
|
||||
fi
|
|
@ -1,9 +1,9 @@
|
|||
[Default]
|
||||
save_dir=$HOME/Pictures/Screenshots
|
||||
early_exit=true
|
||||
line_size=5
|
||||
paint_mode=rectangle
|
||||
save_dir=/home/itsdrike/Media/Pictures/Screenshots
|
||||
save_filename_format=Screenshot_%Y-%M-%d_%H-%M-%S.png
|
||||
show_panel=false
|
||||
line_size=5
|
||||
text_size=20
|
||||
text_font=JetBrains Mono
|
||||
early_exit=true
|
||||
paint_mode=rectangle
|
||||
text_size=20
|
||||
|
|
|
@ -5,9 +5,9 @@ After=eww.service
|
|||
PartOf=eww.service
|
||||
|
||||
[Service]
|
||||
ExecStartPre=/usr/local/bin/eww ping
|
||||
ExecStart=/usr/local/bin/eww open %i
|
||||
ExecStop=/usr/local/bin/eww close %i
|
||||
ExecStartPre=/usr/bin/eww ping
|
||||
ExecStart=/usr/bin/eww open %i
|
||||
ExecStop=/usr/bin/eww close %i
|
||||
Type=oneshot
|
||||
RemainAfterExit=true
|
||||
Restart=on-failure
|
||||
|
|
|
@ -3,7 +3,7 @@ Description="Eww daemon"
|
|||
PartOf=graphical-session.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/eww daemon --no-daemonize
|
||||
ExecStart=/usr/bin/eww daemon --no-daemonize
|
||||
Restart=always
|
||||
RestartSec=3s
|
||||
|
||||
|
|
12
home/.config/systemd/user/hyprpaper.service
Normal file
12
home/.config/systemd/user/hyprpaper.service
Normal file
|
@ -0,0 +1,12 @@
|
|||
[Unit]
|
||||
Description="Hyprpaper (Hyprland wallpaper daemon"
|
||||
PartOf=graphical-session.target
|
||||
After=graphical-session.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/hyprpaper
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=wayland-session.target
|
|
@ -1,12 +0,0 @@
|
|||
[Unit]
|
||||
Description="Wallpaper setter"
|
||||
PartOf=graphical-session.target
|
||||
|
||||
[Service]
|
||||
Environment=WALLPAPER_IMAGE=%h/.local/share/background
|
||||
ExecStart=/usr/bin/swaybg --image $WALLPAPER_IMAGE
|
||||
Restart=always
|
||||
RestartSec=3s
|
||||
|
||||
[Install]
|
||||
WantedBy=wayland-session.target
|
|
@ -0,0 +1 @@
|
|||
/home/itsdrike/.config/systemd/user/hyprpaper.service
|
|
@ -1 +0,0 @@
|
|||
/home/itsdrike/.config/systemd/user/wallpaper.service
|
7
home/.config/tealdeer/config.toml
Normal file
7
home/.config/tealdeer/config.toml
Normal file
|
@ -0,0 +1,7 @@
|
|||
[display]
|
||||
compact = false
|
||||
use_pager = true
|
||||
|
||||
[updates]
|
||||
auto_update = true
|
||||
auto_update_interval_hours = 720
|
|
@ -7,12 +7,10 @@
|
|||
#
|
||||
#XDG_DESKTOP_DIR="$HOME/Desktop"
|
||||
XDG_DOWNLOAD_DIR="$HOME/Downloads"
|
||||
#XDG_TEMPLATES_DIR="$HOME/Templates"
|
||||
#XDG_PUBLICSHARE_DIR="$HOME/Public"
|
||||
XDG_TEMPLATES_DIR="$XDG_DATA_HOME/templates"
|
||||
XDG_PUBLICSHARE_DIR="$XDG_DATA_HOME/public"
|
||||
#XDG_DOCUMENTS_DIR="$HOME/Documents"
|
||||
XDG_DOCUMENTS_DIR="$HOME/Personal"
|
||||
#XDG_MUSIC_DIR="$HOME/Music"
|
||||
XDG_MUSIC_DIR="$HOME/Audio"
|
||||
XDG_PICTURES_DIR="$HOME/Pictures"
|
||||
XDG_SCREENSHOTS_DIR="$HOME/Pictures/Screenshots"
|
||||
XDG_VIDEOS_DIR="$HOME/Videos"
|
||||
XDG_MUSIC_DIR="$HOME/Media/Music"
|
||||
XDG_PICTURES_DIR="$HOME/Media/Pictures"
|
||||
XDG_VIDEOS_DIR="$HOME/Media/Videos"
|
||||
XDG_SCREENSHOTS_DIR="$HOME/Media/Pictures/Screenshots"
|
||||
|
|
5
home/.config/xdg-desktop-portal/portals.conf
Normal file
5
home/.config/xdg-desktop-portal/portals.conf
Normal file
|
@ -0,0 +1,5 @@
|
|||
[preferred]
|
||||
default=gtk
|
||||
org.freedesktop.impl.portal.Screencast=hyprland
|
||||
org.freedesktop.impl.portal.Screenshot=hyprland
|
||||
org.freedesktop.impl.portal.Secret=gnome-keyring
|
9
home/.config/xsettingsd/xsettingsd.conf
Normal file
9
home/.config/xsettingsd/xsettingsd.conf
Normal file
|
@ -0,0 +1,9 @@
|
|||
Net/ThemeName "Tokyonight-Dark"
|
||||
Net/IconThemeName "Papirus-Dark"
|
||||
Gtk/CursorThemeName "BreezeX-RosePine-Linux"
|
||||
Net/EnableEventSounds 1
|
||||
EnableInputFeedbackSounds 0
|
||||
Xft/Antialias 1
|
||||
Xft/Hinting 1
|
||||
Xft/HintStyle "hintslight"
|
||||
Xft/RGBA "rgb"
|
|
@ -1 +0,0 @@
|
|||
../shell/profile
|
16
home/.config/zsh/.zprofile
Executable file
16
home/.config/zsh/.zprofile
Executable file
|
@ -0,0 +1,16 @@
|
|||
#!/bin/zsh
|
||||
|
||||
# User .profile definition.
|
||||
# This file is only sourced once, after login, Unlike
|
||||
# .zshrc/.bashrc, which will run whenever a new terminal
|
||||
# is opened.
|
||||
|
||||
# Start graphical session automatically on tty1 if Hyprland or startx is available
|
||||
#if [ "$(tty)" = "/dev/tty1" ] && [ "$UID" != 0 ]; then
|
||||
# if command -v Hyprland >/dev/null; then
|
||||
# ! pidof -s Hyprland >/dev/null 2>&1 && launch-hypr
|
||||
# elif command -v startx >/dev/null; then
|
||||
# ! pidof -s Xorg >/dev/null 2>&1 && exec startx "$XINITRC"
|
||||
# fi
|
||||
#fi
|
||||
|
|
@ -1,138 +1,22 @@
|
|||
#!/usr/bin/zsh
|
||||
|
||||
#########################
|
||||
# History Configuration #
|
||||
#########################
|
||||
export HISTSIZE=12000
|
||||
export SAVEHIST=10000
|
||||
|
||||
# If the internal history needs to be trimmed to add the current command line, setting this
|
||||
# option will cause the oldest history event that has a duplicate to be lost before losing a
|
||||
# unique event from the list. You should be sure to set the value of HISTSIZE to a larger
|
||||
# number than SAVEHIST in order to give you some room for the duplicated events, otherwise
|
||||
# this option will behave just like HIST_IGNORE_ALL_DUPS once the history fills up with unique
|
||||
# events.
|
||||
setopt hist_expire_dups_first
|
||||
|
||||
# When searching for history entries in the line editor, do not display duplicates of a line
|
||||
# previously found, even if the duplicates are not contiguous.
|
||||
setopt hist_find_no_dups
|
||||
|
||||
# If a new command line being added to the history list duplicates an older one, the older
|
||||
# command is removed from the list (even if it is not the previous event).
|
||||
setopt hist_ignore_all_dups
|
||||
|
||||
# Remove command lines from the history list when the first character on the line is a space,
|
||||
# or when one of the expanded aliases contains a leading space. Only normal aliases (not
|
||||
# global or suffix aliases) have this behaviour. Note that the command lingers in the internal
|
||||
# history until the next command is entered before it vanishes, allowing you to briefly reuse
|
||||
# or edit the line. If you want to make it vanish right away without entering another command,
|
||||
# type a space and press return.
|
||||
setopt hist_ignore_space
|
||||
|
||||
# When writing out the history file, older commands that duplicate newer ones are omitted.
|
||||
setopt hist_save_no_dups
|
||||
|
||||
# This option works like APPEND_HISTORY except that new history lines are added to the $HISTFILE
|
||||
# incrementally (as soon as they are entered), rather than waiting until the shell exits.
|
||||
setopt inc_append_history
|
||||
|
||||
# When using history expansion (such as with sudo !!), on enter, first show the expanded command
|
||||
# and only run it after confirmation (another enter press)
|
||||
setopt hist_verify
|
||||
|
||||
###############
|
||||
# ZSH Options #
|
||||
###############
|
||||
|
||||
setopt auto_cd # cd by typing directory name if it's not a command
|
||||
setopt auto_list # automatically list choices on ambiguous completion
|
||||
setopt auto_menu # automatically use menu completion
|
||||
setopt always_to_end # move cursor to end if word had one match
|
||||
setopt interactivecomments # allow comments in interactive mode
|
||||
setopt magicequalsubst # enable filename expansion for arguments of form `x=expression`
|
||||
setopt notify # report the status of background jobs immediately
|
||||
setopt numericglobsort # sort filenames numerically when it makes sense
|
||||
setopt auto_pushd # Make cd act as pushd
|
||||
setopt globdots # Match files starting with . without specifying it (cd <TAB>)
|
||||
#setopt correct_all # autocorrect commands
|
||||
|
||||
##################
|
||||
# Autocompletion #
|
||||
##################
|
||||
|
||||
autoload -Uz compinit
|
||||
zmodload -i zsh/complist # load completion list
|
||||
compinit -d $ZSH_COMPDUMP # Specify compdump file
|
||||
zstyle ':completion:*' menu select # select completions with arrow keys
|
||||
zstyle ':completion:*' group-name '' # group results by category
|
||||
zstyle ':completion:::::' completer _expand _complete _ignored _approximate #enable approximate matches for completion
|
||||
|
||||
#################
|
||||
# Custom config #
|
||||
#################
|
||||
source ~/.config/zsh/rc/fallback_term.zsh
|
||||
source ~/.config/zsh/rc/history.zsh
|
||||
source ~/.config/zsh/rc/opts.zsh
|
||||
source ~/.config/zsh/rc/completion.zsh
|
||||
source ~/.config/zsh/rc/keybinds.zsh
|
||||
source ~/.config/zsh/rc/prompt.zsh
|
||||
source ~/.config/zsh/rc/cmd_not_found.zsh
|
||||
source ~/.config/zsh/rc/auto_cleanup.zsh
|
||||
|
||||
# Setup aliases
|
||||
[ -f ~/.config/shell/aliases ] && source ~/.config/shell/aliases
|
||||
# Load handlers
|
||||
[ -f ~/.config/shell/handlers ] && source ~/.config/shell/handlers
|
||||
# Load key bindings
|
||||
[ -f ~/.config/shell/keybinds ] && source ~/.config/shell/keybinds
|
||||
# Load prompt
|
||||
[ -f ~/.config/shell/prompt ] && source ~/.config/shell/prompt
|
||||
|
||||
#####################
|
||||
# Automatic Cleanup #
|
||||
#####################
|
||||
|
||||
[ -f ~/.zsh-update ] && mv ~/.zsh-update $ZSH_CACHE/.zsh-update
|
||||
[ -f ~/.sudo_as_admin_sucessful ] && rm ~/.sudo_as_admin_successful
|
||||
[ -f ~/.bash_history ] && rm ~/.bash_history
|
||||
|
||||
# Make sure ZSH_CACHE dir exists, avoiding zsh to create it's cache files
|
||||
# in $HOME
|
||||
mkdir -p "$ZSH_CACHE"
|
||||
|
||||
########
|
||||
# Misc #
|
||||
########
|
||||
|
||||
# Color support
|
||||
#autoload -U colors && colors
|
||||
|
||||
# Define TMOUT timeout for TTY and root
|
||||
# [ -z "$DISPLAY" ] && export TMOUT=800
|
||||
# [ $UID -eq 0 ] && export TMOUT=600
|
||||
|
||||
if command -v pyenv >/dev/null 2>&1; then
|
||||
eval "$(pyenv init -)"
|
||||
fi
|
||||
|
||||
if command -v zoxide >/dev/null 2>&1; then
|
||||
eval "$(zoxide init --cmd z zsh)"
|
||||
fi
|
||||
|
||||
#########################
|
||||
# Zgenom Plugin Manager #
|
||||
#########################
|
||||
|
||||
# Load zgenom (plugin manager for ZSH)
|
||||
source "${ZDOTDIR}/.zgenom/zgenom.zsh"
|
||||
|
||||
# Check for zgenom updates
|
||||
# This does not increase startup time
|
||||
zgenom autoupdate
|
||||
|
||||
# If the init script doesn't exist yet
|
||||
if ! zgenom saved; then
|
||||
zgenom load akash329d/zsh-alias-finder
|
||||
zgenom load clarketm/zsh-completions
|
||||
zgenom load zsh-users/zsh-autosuggestions
|
||||
zgenom load zdharma-continuum/fast-syntax-highlighting
|
||||
|
||||
# Generate the init script from plugins above
|
||||
zgenom save
|
||||
fi
|
||||
source ~/.config/zsh/rc/misc.zsh
|
||||
source ~/.config/zsh/rc/plugins.zsh
|
||||
source ~/.config/zsh/rc/zgenom.zsh
|
||||
|
||||
# Override the comment color to make comments visible on black bg
|
||||
# (this needs to be after zgenom, as it requires the zsh-fast-highlighting plugin
|
||||
# to be loaded)
|
||||
FAST_HIGHLIGHT_STYLES[comment]='fg=#696C76'
|
||||
|
|
8
home/.config/zsh/rc/auto_cleanup.zsh
Normal file
8
home/.config/zsh/rc/auto_cleanup.zsh
Normal file
|
@ -0,0 +1,8 @@
|
|||
# This will simply remove some clutter files from the home directory
|
||||
|
||||
[ -f ~/.zsh-update ] && mv ~/.zsh-update $ZSH_CACHE/.zsh-update
|
||||
[ -f ~/.sudo_as_admin_sucessful ] && rm ~/.sudo_as_admin_successful
|
||||
[ -f ~/.bash_history ] && rm ~/.bash_history
|
||||
|
||||
# Make sure ZSH_CACHE dir exists, avoiding zsh to create it's cache files in $HOME
|
||||
mkdir -p "$ZSH_CACHE"
|
3
home/.config/shell/handlers → home/.config/zsh/rc/cmd_not_found.zsh
Executable file → Normal file
3
home/.config/shell/handlers → home/.config/zsh/rc/cmd_not_found.zsh
Executable file → Normal file
|
@ -1,5 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
if command -v pkgfile > /dev/null; then
|
||||
# Command not found hook that uses `pkgfile` package
|
||||
# to search through the package index in order to find
|
||||
|
@ -38,3 +36,4 @@ elif [ -x /usr/lib/command-not-found ] || [ -x /usr/share/command-not-found/comm
|
|||
fi
|
||||
}
|
||||
fi
|
||||
|
19
home/.config/zsh/rc/completion.zsh
Normal file
19
home/.config/zsh/rc/completion.zsh
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Autocompletion behavior of ZSH
|
||||
|
||||
autoload -Uz compinit
|
||||
zmodload -i zsh/complist # load completion list
|
||||
|
||||
if [[ -n "$(print ${ZDOTDIR:-$HOME}/.zcompdump(Nmh+5))" ]]; then
|
||||
# Re-check for new completions, re-creating .zcompdump if necessary.
|
||||
# This check can be quite slow and it's rare that we actually have new completions to load.
|
||||
# For that reason, we only do this if the compdump file is older than 5 hours.
|
||||
compinit
|
||||
else
|
||||
# This will omit the check for new completions,
|
||||
# only re-creating .zcompdump if it doesn't yet exist.
|
||||
compinit -C
|
||||
fi
|
||||
|
||||
zstyle ':completion:*' menu select # select completions with arrow keys
|
||||
zstyle ':completion:*' group-name '' # group results by category
|
||||
zstyle ':completion:::::' completer _expand _complete _ignored _approximate # enable approximate matches for completion
|
8
home/.config/zsh/rc/fallback_term.zsh
Normal file
8
home/.config/zsh/rc/fallback_term.zsh
Normal file
|
@ -0,0 +1,8 @@
|
|||
# If the set $TERM variable doesn't match any configured terminfo entries
|
||||
# fall back to xterm. This fixes SSH connections from unknown terminals
|
||||
|
||||
if ! infocmp "$TERM" &>/dev/null; then
|
||||
echo "Setting \$TERM to xterm-256color due to missing terminfo entry for $TERM."
|
||||
export TERM=xterm-256color
|
||||
fi
|
||||
|
59
home/.config/zsh/rc/history.zsh
Normal file
59
home/.config/zsh/rc/history.zsh
Normal file
|
@ -0,0 +1,59 @@
|
|||
export HISTSIZE=12000
|
||||
export SAVEHIST=10000
|
||||
|
||||
# Append history list to history file once the session exits, rather than replacing
|
||||
# the history file, erasing any past entries
|
||||
setopt APPEND_HISTORY
|
||||
|
||||
# If the internal history needs to be trimmed to add the current command line, setting this
|
||||
# option will cause the oldest history event that has a duplicate to be lost before losing a
|
||||
# unique event from the list. You should be sure to set the value of HISTSIZE to a larger
|
||||
# number than SAVEHIST in order to give you some room for the duplicated events, otherwise
|
||||
# this option will behave just like HIST_IGNORE_ALL_DUPS once the history fills up with unique
|
||||
# events.
|
||||
setopt HIST_EXPIRE_DUPS_FIRST
|
||||
|
||||
# When searching for history entries in the line editor, do not display duplicates of a line
|
||||
# previously found, even if the duplicates are not contiguous.
|
||||
setopt HIST_FIND_NO_DUPS
|
||||
|
||||
# If a new command line being added to the history list duplicates an older one, the older
|
||||
# command is removed from the list (even if it is not the previous event).
|
||||
setopt HIST_IGNORE_ALL_DUPS
|
||||
|
||||
# Remove command lines from the history list when the first character on the line is a space,
|
||||
# or when one of the expanded aliases contains a leading space. Only normal aliases (not
|
||||
# global or suffix aliases) have this behaviour. Note that the command lingers in the internal
|
||||
# history until the next command is entered before it vanishes, allowing you to briefly reuse
|
||||
# or edit the line. If you want to make it vanish right away without entering another command,
|
||||
# type a space and press return.
|
||||
setopt HIST_IGNORE_SPACE
|
||||
|
||||
# When writing out the history file, older commands that duplicate newer ones are omitted.
|
||||
setopt HIST_SAVE_NO_DUPS
|
||||
|
||||
# This option works like APPEND_HISTORY except that new history lines are added to the $HISTFILE
|
||||
# incrementally (as soon as they are entered), rather than waiting until the shell exits.
|
||||
setopt INC_APPEND_HISTORY
|
||||
|
||||
# When using history expansion (such as with sudo !!), on enter, first show the expanded command
|
||||
# and only run it after confirmation (another enter press)
|
||||
setopt HIST_VERIFY
|
||||
|
||||
# Remove superfluous blanks from each command line being added to the history list
|
||||
setopt HIST_REDUCE_BLANKS
|
||||
|
||||
# When writing out the history file, by default zsh uses ad-hoc file locking to avoid known
|
||||
# problems with locking on some operating systems. With this option, locking is done by means
|
||||
# of the `fcntl` system call, where this method is available. This can improve performance on
|
||||
# recent operating systems, and is better at avoiding history corruption when files are stored
|
||||
# on NFS.
|
||||
setopt HIST_FCNTL_LOCK
|
||||
|
||||
# Save each command's beginning time (unix timestamp) and the duration (in seconds) to the
|
||||
# history file.
|
||||
setopt EXTENDED_HISTORY
|
||||
|
||||
# beep in ZLE when a widget attempts to access a history entry which isn’t there
|
||||
unsetopt HIST_BEEP
|
||||
|
2
home/.config/shell/keybinds → home/.config/zsh/rc/keybinds.zsh
Executable file → Normal file
2
home/.config/shell/keybinds → home/.config/zsh/rc/keybinds.zsh
Executable file → Normal file
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env zsh
|
||||
# shellcheck disable=SC2030,SC2031,SC2015
|
||||
# Set default keybindings (mostly from oh-my-zsh)
|
||||
|
||||
|
@ -63,3 +62,4 @@ bindkey ' ' magic-space
|
|||
|
||||
# [ctrl+space] Accept suggestion from zsh-autosuggestions plugin
|
||||
bindkey '^ ' autosuggest-accept
|
||||
|
15
home/.config/zsh/rc/misc.zsh
Normal file
15
home/.config/zsh/rc/misc.zsh
Normal file
|
@ -0,0 +1,15 @@
|
|||
# This file contains miscellaneous configurations,
|
||||
# usually required by external applications that isn't suited for plugins.zsh
|
||||
# or just general ZSH/shell settings that don't fit anywhere else
|
||||
|
||||
# Foot terminal uses this sequence to identify a command execution
|
||||
# that way it's possible to use ctrl+shift+z/x to jump between commands
|
||||
if [ "$TERM" = "foot" ]; then
|
||||
precmd() {
|
||||
print -Pn "\e]133;A\e\\"
|
||||
}
|
||||
fi
|
||||
|
||||
# Define TMOUT timeout for TTY and root
|
||||
# [ -z "$DISPLAY" ] && export TMOUT=800
|
||||
# [ $UID -eq 0 ] && export TMOUT=600
|
31
home/.config/zsh/rc/opts.zsh
Normal file
31
home/.config/zsh/rc/opts.zsh
Normal file
|
@ -0,0 +1,31 @@
|
|||
# Set or unset various zsh options.
|
||||
# You can read more about what options are available and what these do in
|
||||
# the ZSH manual: <https://zsh.sourceforge.io/Doc/Release/Options.html>
|
||||
#
|
||||
# Note that history-related options are set from history.zsh, not from here.
|
||||
|
||||
#########################
|
||||
# General/Other options #
|
||||
#########################
|
||||
|
||||
setopt AUTO_CD # cd by typing directory name if it's not a command
|
||||
setopt AUTO_LIST # automatically list choices on ambiguous completion
|
||||
setopt AUTO_MENU # automatically use menu completion
|
||||
setopt MENU_COMPLETE # insert first match immediately on ambiguous completion
|
||||
setopt AUTO_PARAM_SLASH # if a parameter is completed with a directory, add trailing slash instead of space
|
||||
setopt ALWAYS_TO_END # move cursor to end if word had one match
|
||||
setopt INTERACTIVE_COMMENTS # allow comments in interactive mode
|
||||
setopt MAGIC_EQUAL_SUBST # enable filename expansion for arguments of form `x=expression`
|
||||
setopt NOTIFY # report the status of background jobs immediately
|
||||
setopt NUMERIC_GLOB_SORT # sort filenames numerically when it makes sense
|
||||
setopt GLOB_DOTS # Match files starting with . without specifying it (cd <TAB>)
|
||||
|
||||
|
||||
######################
|
||||
# Auto pushd options #
|
||||
######################
|
||||
|
||||
setopt AUTO_PUSHD # Make cd push the old directory onto the directory stack
|
||||
setopt PUSHD_IGNORE_DUPS # don't push multiple copies of the same directory
|
||||
setopt PUSHD_TO_HOME # have pushd with no arguments act like `pushd $HOME`
|
||||
setopt PUSHD_SILENT # do not print the directory stack
|
15
home/.config/zsh/rc/plugins.zsh
Normal file
15
home/.config/zsh/rc/plugins.zsh
Normal file
|
@ -0,0 +1,15 @@
|
|||
# This file loads custom ZSH plugins or runs shell configurations
|
||||
# exposed by various plugins. This often includes custom autocompletions,
|
||||
# but also whatever other functionalities that these may contain.
|
||||
|
||||
if command -v pyenv >/dev/null 2>&1; then
|
||||
eval "$(pyenv init -)"
|
||||
fi
|
||||
|
||||
if command -v zoxide >/dev/null 2>&1; then
|
||||
eval "$(zoxide init zsh --cmd z)"
|
||||
fi
|
||||
|
||||
if command -v eww >/dev/null 2>&1; then
|
||||
eval "$(eww shell-completions --shell zsh)"
|
||||
fi
|
|
@ -185,3 +185,4 @@ else
|
|||
RPS1="%(?..${RED}%? ↵$RESET)"
|
||||
fi
|
||||
|
||||
|
18
home/.config/zsh/rc/zgenom.zsh
Normal file
18
home/.config/zsh/rc/zgenom.zsh
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Load zgenom (plugin manager for ZSH)
|
||||
source "${ZDOTDIR}/.zgenom/zgenom.zsh"
|
||||
|
||||
# Check for zgenom updates
|
||||
# This does not increase startup time
|
||||
zgenom autoupdate
|
||||
|
||||
# If the init script doesn't exist yet
|
||||
if ! zgenom saved; then
|
||||
zgenom load akash329d/zsh-alias-finder
|
||||
zgenom load clarketm/zsh-completions
|
||||
zgenom load zsh-users/zsh-autosuggestions
|
||||
zgenom load zdharma-continuum/fast-syntax-highlighting
|
||||
|
||||
# Generate the init script from plugins above
|
||||
zgenom save
|
||||
fi
|
||||
|
57
home/.local/bin/scripts/cli/better-git-branch
Executable file
57
home/.local/bin/scripts/cli/better-git-branch
Executable file
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/env bash
|
||||
# Source: https://gist.github.com/schacon/e9e743dee2e92db9a464619b99e94eff
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
NO_COLOR='\033[0m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[0;33m'
|
||||
NO_COLOR='\033[0m'
|
||||
|
||||
width1=5
|
||||
width2=6
|
||||
width3=30
|
||||
width4=20
|
||||
width5=20
|
||||
|
||||
# Function to count commits
|
||||
count_commits() {
|
||||
local branch="$1"
|
||||
local base_branch="$2"
|
||||
local ahead_behind
|
||||
|
||||
ahead_behind=$(git rev-list --left-right --count "$base_branch"..."$branch")
|
||||
echo "$ahead_behind"
|
||||
}
|
||||
|
||||
# Main script
|
||||
main_branch=$(git rev-parse HEAD)
|
||||
|
||||
printf "${GREEN}%-${width1}s ${RED}%-${width2}s ${BLUE}%-${width3}s ${YELLOW}%-${width4}s ${NO_COLOR}%-${width5}s\n" "Ahead" "Behind" "Branch" "Last Commit" " "
|
||||
|
||||
# Separator line for clarity
|
||||
printf "${GREEN}%-${width1}s ${RED}%-${width2}s ${BLUE}%-${width3}s ${YELLOW}%-${width4}s ${NO_COLOR}%-${width5}s\n" "-----" "------" "------------------------------" "-------------------" " "
|
||||
|
||||
format_string="%(objectname:short)@%(refname:short)@%(committerdate:relative)"
|
||||
IFS=$'\n'
|
||||
|
||||
for branchdata in $(git for-each-ref --sort=-authordate --format="$format_string" refs/heads/ --no-merged); do
|
||||
sha=$(echo "$branchdata" | cut -d '@' -f1)
|
||||
branch=$(echo "$branchdata" | cut -d '@' -f2)
|
||||
time=$(echo "$branchdata" | cut -d '@' -f3)
|
||||
if [ "$branch" != "$main_branch" ]; then
|
||||
# Get branch description
|
||||
description=$(git config branch."$branch".description)
|
||||
|
||||
# Count commits ahead and behind
|
||||
ahead_behind=$(count_commits "$sha" "$main_branch")
|
||||
ahead=$(echo "$ahead_behind" | cut -f2)
|
||||
behind=$(echo "$ahead_behind" | cut -f1)
|
||||
|
||||
# Display branch info
|
||||
# shellcheck disable=SC2086
|
||||
printf "${GREEN}%-${width1}s ${RED}%-${width2}s ${BLUE}%-${width3}s ${YELLOW}%-${width4}s ${NO_COLOR}%-${width5}s\n" $ahead $behind $branch "$time" "$description"
|
||||
fi
|
||||
done
|
||||
|
36
home/.local/bin/scripts/gui/hyprland/hyprland-move-window
Normal file
36
home/.local/bin/scripts/gui/hyprland/hyprland-move-window
Normal file
|
@ -0,0 +1,36 @@
|
|||
#!/bin/sh
|
||||
|
||||
RESIZE_SIZE=${1:?Missing resize size}
|
||||
|
||||
RESIZE_PARAMS_X=0
|
||||
RESIZE_PARAMS_Y=0
|
||||
|
||||
DIRECTION=${2:?Missing move direction}
|
||||
case $DIRECTION in
|
||||
l)
|
||||
RESIZE_PARAMS_X=-$RESIZE_SIZE
|
||||
;;
|
||||
r)
|
||||
RESIZE_PARAMS_X=$RESIZE_SIZE
|
||||
;;
|
||||
u)
|
||||
RESIZE_PARAMS_Y=-$RESIZE_SIZE
|
||||
;;
|
||||
d)
|
||||
RESIZE_PARAMS_Y=$RESIZE_SIZE
|
||||
;;
|
||||
*)
|
||||
echo "kbye"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
ACTIVE_WINDOW=$(hyprctl activewindow -j)
|
||||
IS_FLOATING=$(echo "$ACTIVE_WINDOW" | jq .floating)
|
||||
|
||||
if [ "$IS_FLOATING" = "true" ]; then
|
||||
hyprctl dispatch moveactive "$RESIZE_PARAMS_X" "$RESIZE_PARAMS_Y"
|
||||
else
|
||||
hyprctl dispatch movewindow "$DIRECTION"
|
||||
fi
|
||||
|
216
home/.local/bin/scripts/gui/hyprland/hyprland-screenshot
Executable file
216
home/.local/bin/scripts/gui/hyprland/hyprland-screenshot
Executable file
|
@ -0,0 +1,216 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Inspired by grimblast (https://github.com/hyprwm/contrib/blob/main/grimblast/grimblast)
|
||||
|
||||
# Helper functions
|
||||
|
||||
die() {
|
||||
MSG="${1}"
|
||||
ERR_CODE="${2:-1}"
|
||||
URGENCY="${3:-critical}"
|
||||
|
||||
>&2 echo "$MSG"
|
||||
if [ "$NOTIFY" = "yes" ]; then
|
||||
notify-send -a screenshot -u "$URGENCY" "Error ($ERR_CODE)" "$MSG"
|
||||
fi
|
||||
exit "$ERR_CODE"
|
||||
}
|
||||
|
||||
# Argument parsing
|
||||
|
||||
SAVE_METHOD=
|
||||
SAVE_FILE=
|
||||
TARGET=
|
||||
NOTIFY=no
|
||||
CURSOR=no
|
||||
EDIT=no
|
||||
DELAY=0
|
||||
|
||||
while [ "${1-}" ]; do
|
||||
case "$1" in
|
||||
-h | --help)
|
||||
>&2 cat <<EOF
|
||||
screenshot taking utility script, allowing for easy all-in-one solution for
|
||||
controlling how a screenshot should be taken.
|
||||
|
||||
Methods (one is required):
|
||||
--copy: Copy the screenshot data into the clipboard
|
||||
--save [FILE]: Save the screenshot data into a file
|
||||
--copysave [FILE]: Both save to clipboard and to file
|
||||
General options:
|
||||
--notify: Send a notification that the screenshot was saved
|
||||
--cursor: Capture cursor in the screenshot
|
||||
--edit: Once the screenshot is taken, edit it first with swappy
|
||||
--delay [MILISECONDS]: Wait for given time until the screenshot is taken
|
||||
--target [TARGET]: (REQUIRED) What should be captured
|
||||
Variables:
|
||||
FILE: A path to a .png image file for output, or '-' to pipe to STDOUT
|
||||
MILISECONDS: Number of miliseconds; Must be a whole, non-negative number!
|
||||
TARGET: Area on screen; can be one of:
|
||||
- activewin: Currently active window
|
||||
- window: Manually select a window
|
||||
- activemon: Currently active monitor (output)
|
||||
- monitor: Manually select a monitor
|
||||
- all: Everything (all visible monitors/outputs)
|
||||
- area: Manually select a region
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
--notify)
|
||||
NOTIFY=yes
|
||||
shift
|
||||
;;
|
||||
--cursor)
|
||||
CURSOR=yes
|
||||
shift
|
||||
;;
|
||||
--edit)
|
||||
EDIT=yes
|
||||
shift
|
||||
;;
|
||||
--target)
|
||||
if [ -z "$TARGET" ]; then
|
||||
case "$2" in
|
||||
activewin | window | activemon | monitor | all | area)
|
||||
TARGET="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
die "Invalid target (see TARGET variable in --help)"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
die "Only one target can be passed."
|
||||
fi
|
||||
;;
|
||||
--delay)
|
||||
case "$2" in
|
||||
'' | *[!0-9]*)
|
||||
die "Argument after --delay must be an amount of MILISECONDS"
|
||||
;;
|
||||
*)
|
||||
DELAY="$2"
|
||||
shift 2
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
--copy)
|
||||
if [ -z "$SAVE_METHOD" ]; then
|
||||
SAVE_METHOD="copy"
|
||||
shift
|
||||
else
|
||||
die "Only one method can be passed."
|
||||
fi
|
||||
;;
|
||||
--save)
|
||||
if [ -z "$SAVE_METHOD" ]; then
|
||||
SAVE_METHOD="save"
|
||||
SAVE_FILE="$2"
|
||||
shift 2
|
||||
else
|
||||
die "Only one method can be passed."
|
||||
fi
|
||||
;;
|
||||
--copysave)
|
||||
if [ -z "$SAVE_METHOD" ]; then
|
||||
SAVE_METHOD="copysave"
|
||||
SAVE_FILE="$2"
|
||||
shift 2
|
||||
else
|
||||
die "Only one method can be passed."
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
die "Unrecognized argument: $1"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Screenshot functions
|
||||
|
||||
takeScreenshot() {
|
||||
FILE="$1"
|
||||
GEOM="$2"
|
||||
|
||||
ARGS=()
|
||||
[ "$CURSOR" = "yes" ] && ARGS+=("-c")
|
||||
[ -n "$GEOM" ] && ARGS+=("-g" "$GEOM")
|
||||
ARGS+=("$FILE")
|
||||
|
||||
sleep "$DELAY"e-3
|
||||
grim "${ARGS[@]}" || die "Unable to invoke grim"
|
||||
}
|
||||
|
||||
takeEditedScreenshot() {
|
||||
FILE="$1"
|
||||
GEOM="$2"
|
||||
|
||||
if [ "$EDIT" = "yes" ]; then
|
||||
takeScreenshot - "$GEOM" | swappy -f - -o "$FILE" || die "Unable to invoke swappy"
|
||||
else
|
||||
takeScreenshot "$FILE" "$GEOM"
|
||||
fi
|
||||
}
|
||||
|
||||
# Obtain the geometry for screenshot to be taken at
|
||||
|
||||
if [ "$TARGET" = "area" ]; then
|
||||
GEOM="$(slurp -d)"
|
||||
if [ -z "$GEOM" ]; then
|
||||
die "No area selected" 2 normal
|
||||
fi
|
||||
WHAT="Area"
|
||||
elif [ "$TARGET" = "all" ]; then
|
||||
GEOM=""
|
||||
WHAT="Screen"
|
||||
elif [ "$TARGET" = "activewin" ]; then
|
||||
FOCUSED="$(hyprctl activewindow -j)"
|
||||
GEOM="$(echo "$FOCUSED" | jq -r '"\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"')"
|
||||
APP_ID="$(echo "$FOCUSED" | jq -r '.class')"
|
||||
WHAT="$APP_ID window"
|
||||
elif [ "$TARGET" = "window" ]; then
|
||||
WORKSPACES="$(hyprctl monitors -j | jq -r 'map(.activeWorkspace.id)')"
|
||||
WINDOWS="$(hyprctl clients -j | jq -r --argjson workspaces "$WORKSPACES" 'map(select([.workspace.id] | inside($workspaces)))')"
|
||||
GEOM=$(echo "$WINDOWS" | jq -r '.[] | "\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"' | slurp -r)
|
||||
if [ -z "$GEOM" ]; then
|
||||
die "No window selected" 2 normal
|
||||
fi
|
||||
WHAT="Window"
|
||||
elif [ "$TARGET" = "activemon" ]; then
|
||||
ACTIVEMON="$(hyprctl monitors -j | jq -r '.[] | select(.focused == true)')"
|
||||
GEOM="$(echo "$ACTIVEMON" | jq -r '"\(.x),\(.y) \(.width)x\(.height)"')"
|
||||
WHAT="$(echo "$ACTIVEMON" | jq -r '.name')"
|
||||
elif [ "$TARGET" = "monitor" ]; then
|
||||
GEOM="$(slurp -o)"
|
||||
if [ -z "$GEOM" ]; then
|
||||
die "No monitor selected" 2 normal
|
||||
fi
|
||||
WHAT="Monitor"
|
||||
else
|
||||
if [ -z "$TARGET" ]; then
|
||||
die "No target specified!"
|
||||
else
|
||||
die "Unknown target: $SAVE_METHOD"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Invoke grim and capture the screenshot
|
||||
|
||||
if [ "$SAVE_METHOD" = "save" ]; then
|
||||
takeEditedScreenshot "$SAVE_FILE" "$GEOM"
|
||||
[ "$NOTIFY" = "yes" ] && notify-send -a screenshot "Success" "$WHAT screenshot saved" -i "$(realpath "$SAVE_FILE")"
|
||||
elif [ "$SAVE_METHOD" = "copy" ]; then
|
||||
TEMP_FILE="$(mktemp --suffix=.png)"
|
||||
takeEditedScreenshot "-" "$GEOM" | tee "$TEMP_FILE" | wl-copy --type image/png || die "Clipboard error"
|
||||
[ "$NOTIFY" = "yes" ] && notify-send -a screenshot "Success" "$WHAT screenshot copied" -i "$(realpath "$TEMP_FILE")" && rm "$TEMP_FILE"
|
||||
elif [ "$SAVE_METHOD" = "copysave" ]; then
|
||||
takeEditedScreenshot "-" "$GEOM" | tee "$SAVE_FILE" | wl-copy --type image/png || die "Clipboard error"
|
||||
[ "$NOTIFY" = "yes" ] && notify-send -a screenshot "Success" "$WHAT screenshot copied and saved" -i "$(realpath "$SAVE_FILE")"
|
||||
else
|
||||
if [ -z "$SAVE_METHOD" ]; then
|
||||
die "No save method specified!"
|
||||
else
|
||||
die "Unknown save method: $SAVE_METHOD"
|
||||
fi
|
||||
fi
|
|
@ -1,17 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# export LIBVA_DRIVER_NAME=nvidia
|
||||
# export XDG_SESSION_TYPE=wayland
|
||||
# export __GLX_VENDOR_LIBRARY_NAME=nvidia
|
||||
# export WLR_NO_HARDWARE_CURSORS=1
|
||||
# export GBM_BACKEND=nvidia-drm # can cause issues
|
||||
|
||||
HYPRLAND_LOG="${XDG_CACHE_HOME:-$HOME/.cache}/hyprlog.txt"
|
||||
|
||||
echo "---------- NEW RUN $(date) ----------" >> "$HYPRLAND_LOG"
|
||||
Hyprland 2>&1 | awk '{ print strftime("%s: "), $0, fflush(); }' | tee -a "$HYPRLAND_LOG"
|
||||
echo "---------- ENDED $(date) ----------" >> "$HYPRLAND_LOG"
|
||||
|
||||
if systemctl --user is-active wayland-session.target &>/dev/null; then
|
||||
systemctl --user stop wayland-session.target
|
||||
fi
|
|
@ -1,226 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Inspired by grimblast (https://github.com/hyprwm/contrib/blob/main/grimblast/grimblast)
|
||||
|
||||
# Requirements:
|
||||
# - `grim`: screenshot utility for wayland
|
||||
# - `slurp`: to select an area
|
||||
# - `hyprctl`: to read properties of current window
|
||||
# - `wl-copy`: clipboard utility
|
||||
# - `jq`: json utility to parse hyprctl output
|
||||
# - `notify-send`: to show notifications
|
||||
# - `swappy`: for editing the screenshots (only required for --edit)
|
||||
|
||||
# Helper functions
|
||||
|
||||
die() {
|
||||
MSG="${1}"
|
||||
ERR_CODE="${2:-1}"
|
||||
URGENCY="${3:-critical}"
|
||||
|
||||
>&2 echo "$MSG"
|
||||
if [ "$NOTIFY" = "yes" ]; then
|
||||
notify-send -a screenshot -u "$URGENCY" "Error ($ERR_CODE)" "$MSG"
|
||||
fi
|
||||
exit "$ERR_CODE"
|
||||
}
|
||||
|
||||
# Argument parsing
|
||||
|
||||
SAVE_METHOD=
|
||||
SAVE_FILE=
|
||||
TARGET=
|
||||
NOTIFY=no
|
||||
CURSOR=no
|
||||
EDIT=no
|
||||
DELAY=0
|
||||
|
||||
while [ "$1" ]; do
|
||||
case "$1" in
|
||||
-h | --help)
|
||||
>&2 cat << EOF
|
||||
screenshot taking utility script, allowing for easy all-in-one solution for
|
||||
controlling how a screenshot should be taken.
|
||||
|
||||
Methods (one is required):
|
||||
--copy: Copy the screenshot data into the clipboard
|
||||
--save [FILE]: Save the screenshot data into a file
|
||||
--copysave [FILE]: Both save to clipboard and to file
|
||||
General options:
|
||||
--notify: Send a notification that the screenshot was saved
|
||||
--cursor: Capture cursor in the screenshot
|
||||
--edit: Once the screenshot is taken, edit it first with swappy
|
||||
--delay [MILISECONDS]: Wait for given time until the screenshot is taken
|
||||
--target [TARGET]: (REQUIRED) What should be captured
|
||||
Variables:
|
||||
FILE: A path to a .png image file for output, or '-' to pipe to STDOUT
|
||||
MILISECONDS: Number of miliseconds; Must be a whole, non-negative number!
|
||||
TARGET: Area on screen; can be one of:
|
||||
- activewin: Currently active window
|
||||
- window: Manually select a window
|
||||
- activemon: Currently active monitor (output)
|
||||
- monitor: Manually select a monitor
|
||||
- all: Everything (all visible monitors/outputs)
|
||||
- area: Manually select a region
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
--notify)
|
||||
NOTIFY=yes
|
||||
shift
|
||||
;;
|
||||
--cursor)
|
||||
CURSOR=yes
|
||||
shift
|
||||
;;
|
||||
--edit)
|
||||
EDIT=yes
|
||||
shift
|
||||
;;
|
||||
--target)
|
||||
if [ -z "$TARGET" ]; then
|
||||
case "$2" in
|
||||
activewin|window|activemon|monitor|all|area)
|
||||
TARGET="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
die "Invalid target (see TARGET variable in --help)"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
die "Only one target can be passed."
|
||||
fi
|
||||
;;
|
||||
--delay)
|
||||
case "$2" in
|
||||
''|*[!0-9]*)
|
||||
die "Argument after --delay must be an amount of MILISECONDS"
|
||||
;;
|
||||
*)
|
||||
DELAY="$2"
|
||||
shift 2
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
--copy)
|
||||
if [ -z "$SAVE_METHOD" ]; then
|
||||
SAVE_METHOD="copy"
|
||||
shift
|
||||
else
|
||||
die "Only one method can be passed."
|
||||
fi
|
||||
;;
|
||||
--save)
|
||||
if [ -z "$SAVE_METHOD" ]; then
|
||||
SAVE_METHOD="save"
|
||||
SAVE_FILE="$2"
|
||||
shift 2
|
||||
else
|
||||
die "Only one method can be passed."
|
||||
fi
|
||||
;;
|
||||
--copysave)
|
||||
if [ -z "$SAVE_METHOD" ]; then
|
||||
SAVE_METHOD="copysave"
|
||||
SAVE_FILE="$2"
|
||||
shift 2
|
||||
else
|
||||
die "Only one method can be passed."
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
die "Unrecognized argument: $1"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Screenshot functions
|
||||
|
||||
takeScreenshot() {
|
||||
FILE="$1"
|
||||
GEOM="$2"
|
||||
|
||||
ARGS=()
|
||||
[ "$CURSOR" = "yes" ] && ARGS+=("-c")
|
||||
[ -n "$GEOM" ] && ARGS+=("-g" "$GEOM")
|
||||
ARGS+=("$FILE")
|
||||
|
||||
sleep "$DELAY"e-3
|
||||
grim "${ARGS[@]}" || die "Unable to invoke grim"
|
||||
}
|
||||
|
||||
takeEditedScreenshot() {
|
||||
FILE="$1"
|
||||
GEOM="$2"
|
||||
|
||||
if [ "$EDIT" = "yes" ]; then
|
||||
takeScreenshot - "$GEOM" | swappy -f - -o "$FILE" || die "Unable to invoke swappy"
|
||||
else
|
||||
takeScreenshot "$FILE" "$GEOM"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Obtain the geometry for screenshot to be taken at
|
||||
|
||||
if [ "$TARGET" = "area" ]; then
|
||||
GEOM="$(slurp -d)"
|
||||
if [ -z "$GEOM" ]; then
|
||||
die "No area selected" 2 normal
|
||||
fi
|
||||
WHAT="Area"
|
||||
elif [ "$TARGET" = "all" ]; then
|
||||
GEOM=""
|
||||
WHAT="Screen"
|
||||
elif [ "$TARGET" = "activewin" ]; then
|
||||
FOCUSED="$(hyprctl activewindow -j)"
|
||||
GEOM="$(echo "$FOCUSED" | jq -r '"\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"')"
|
||||
APP_ID="$(echo "$FOCUSED" | jq -r '.class')"
|
||||
WHAT="$APP_ID window"
|
||||
elif [ "$TARGET" = "window" ]; then
|
||||
WORKSPACES="$(hyprctl monitors -j | jq -r 'map(.activeWorkspace.id)')"
|
||||
WINDOWS="$(hyprctl clients -j | jq -r --argjson workspaces "$WORKSPACES" 'map(select([.workspace.id] | inside($workspaces)))' )"
|
||||
GEOM=$(echo "$WINDOWS" | jq -r '.[] | "\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"' | slurp -r)
|
||||
if [ -z "$GEOM" ]; then
|
||||
die "No window selected" 2 normal
|
||||
fi
|
||||
WHAT="Window"
|
||||
elif [ "$TARGET" = "activemon" ]; then
|
||||
ACTIVEMON="$(hyprctl monitors -j | jq -r '.[] | select(.focused == true)')"
|
||||
GEOM="$(echo "$ACTIVEMON" | jq -r '"\(.x),\(.y) \(.width)x\(.height)"')"
|
||||
WHAT="$(echo "$ACTIVEMON" | jq -r '.name')"
|
||||
elif [ "$TARGET" = "monitor" ]; then
|
||||
GEOM="$(slurp -o)"
|
||||
if [ -z "$GEOM" ]; then
|
||||
die "No monitor selected" 2 normal
|
||||
fi
|
||||
WHAT="Monitor"
|
||||
else
|
||||
if [ -z "$TARGET" ]; then
|
||||
die "No target specified!"
|
||||
else
|
||||
die "Unknown target: $SAVE_METHOD"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Invoke grim and capture the screenshot
|
||||
|
||||
if [ "$SAVE_METHOD" = "save" ]; then
|
||||
takeEditedScreenshot "$SAVE_FILE" "$GEOM"
|
||||
notify-send -a screenshot "Success" "$WHAT screenshot saved" -i "$(realpath "$SAVE_FILE")"
|
||||
elif [ "$SAVE_METHOD" = "copy" ]; then
|
||||
TEMP_FILE="$(mktemp --suffix=.png)"
|
||||
takeEditedScreenshot "-" "$GEOM" | tee "$TEMP_FILE" | wl-copy --type image/png || die "Clipboard error"
|
||||
notify-send -a screenshot "Success" "$WHAT screenshot copied" -i "$(realpath "$TEMP_FILE")" && rm "$TEMP_FILE"
|
||||
elif [ "$SAVE_METHOD" = "copysave" ]; then
|
||||
takeEditedScreenshot "-" "$GEOM" | tee "$SAVE_FILE" | wl-copy --type image/png || die "Clipboard error"
|
||||
notify-send -a screenshot "Success" "$WHAT screenshot copied and saved" -i "$(realpath "$SAVE_FILE")"
|
||||
else
|
||||
if [ -z "$SAVE_METHOD" ]; then
|
||||
die "No save method specified!"
|
||||
else
|
||||
die "Unknown save method: $SAVE_METHOD"
|
||||
fi
|
||||
fi
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue