Compare commits

..

1 commit

Author SHA1 Message Date
Geoffrey Frogeye d8ae0467c3 Attempt at recoloring the background declaratively 2023-12-24 22:01:58 +01:00
147 changed files with 2750 additions and 4530 deletions

5
.gitignore vendored
View file

@ -1,2 +1,5 @@
result
*/hm
*/system
*/vm
*/vmWithBootLoader
*.qcow2

View file

@ -28,6 +28,7 @@ It is built on top of the Nix ecosystem
## Scripts
They all have a `-h` flag.
Except `add_channels.sh`, which should be removed as soon as I migrate to Flakes.
## Extensions

8
add_channels.sh Executable file
View file

@ -0,0 +1,8 @@
#!/usr/bin/env bash
# TODO Flakes
nix-channel --add https://nixos.org/channels/nixos-23.11 nixpkgs
nix-channel --add https://github.com/nix-community/home-manager/archive/release-23.11.tar.gz home-manager
nix-channel --add https://github.com/NixOS/nixos-hardware/archive/8772491ed75f150f02552c60694e1beff9f46013.tar.gz nixos-hardware
nix-channel --update

70
build_hm.sh Executable file
View file

@ -0,0 +1,70 @@
#!/usr/bin/env nix-shell
#! nix-shell -i bash
#! nix-shell -p bash nix-output-monitor
set -euo pipefail
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
# Parse arguments
function help {
echo "Usage: $0 [-h|-v|-b] profile"
echo "Build Home Manager configuration on the local machine."
echo
echo "Arguments:"
echo " profile: Home Manager profile to use"
echo
echo "Options:"
echo " -h: Display this help message."
}
while getopts "h" OPTION
do
case "$OPTION" in
h)
help
exit 0
;;
?)
help
exit 2
;;
esac
done
shift "$(($OPTIND -1))"
if [ "$#" -ne 1 ]
then
help
exit 2
fi
profile="$1"
profile_dir="${SCRIPT_DIR}/${profile}"
if [ ! -d "$profile_dir" ]
then
echo "Profile not found."
fi
home_manager_config="${profile_dir}/hm.nix"
if [ ! -f "$home_manager_config" ]
then
echo "Home Manager configuration not found."
fi
set -x
nom-build '<home-manager/home-manager/home-manager.nix>' --argstr confPath "${home_manager_config}" -o "${profile_dir}/hm"
set +x
echo 
path="$(readlink -f "${profile_dir}/hm")"
echo "Manual installation instructions:"
echo "- Transfer $path and dependencies to the destination machine (somehow)"
echo "- Run $path/activate as the destination user"
echo "- Log into the user again to make sure everything is sourced"
echo "- Transfer necessary private keys (or use ssh -A for testing)"
echo "- Run git-sync-init"
echo "- Check that the system can build itself"

View file

@ -1,14 +1,14 @@
#!/usr/bin/env nix-shell
#! nix-shell -i bash
#! nix-shell -p nix
#! nix-shell -p bash nix-output-monitor
set -euo pipefail
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
# Parse arguments
function help {
echo "Usage: $0 [-h|-e|-b] [flake-uri#]name"
echo "Build a NixOS configuration on the local machine."
echo "Usage: $0 [-h|-v|-b] profile"
echo "Build NixOS configuration on the local machine."
echo
echo "Arguments:"
echo " profile: OS/disk profile to use"
@ -19,7 +19,7 @@ function help {
echo " -b: Build a virtual machine with boot loader."
}
arg=build
attr=system
while getopts "hvb" OPTION
do
case "$OPTION" in
@ -28,10 +28,10 @@ do
exit 0
;;
v)
arg=build-vm
attr=vm
;;
b)
arg=build-vm-with-bootloader
attr=vmWithBootLoader
;;
?)
help
@ -39,35 +39,29 @@ do
;;
esac
done
shift "$((OPTIND -1))"
shift "$(($OPTIND -1))"
if [ "$#" -ne 1 ]
then
help
exit 2
fi
profile="$1"
if [[ "$1" == *"#"* ]]
profile_dir="${SCRIPT_DIR}/${profile}"
if [ ! -d "$profile_dir" ]
then
flake_uri="$(echo "$1" | cut -d'#' -f1)"
flake_uri=$( cd -- "$flake_uri" &> /dev/null && pwd )
name="$(echo "$1" | cut -d'#' -f2)"
else
flake_uri="$SCRIPT_DIR"
name="$1"
echo "Profile not found."
fi
if [ ! -f "$flake_uri/flake.nix" ]
nixos_config="${profile_dir}/os.nix"
if [ ! -f "$nixos_config" ]
then
echo "Flake not found."
echo "NixOS configuration not found."
fi
flake="${flake_uri}#${name}"
set -x
nix --extra-experimental-features "nix-command flakes" run "${SCRIPT_DIR}#nixos-rebuild" -- "$arg" --flake "$flake"
nom-build '<nixpkgs/nixos>' -I "nixos-config=${nixos_config}" -A "$attr" -o "${profile_dir}/${attr}"
echo 
# TODO Use update-local-flakes?

View file

@ -1,22 +0,0 @@
{ pkgs, lib, config, ... }:
let
generator = pkgs.writers.writePython3 "frogarized"
{
libraries = [ pkgs.python3Packages.colorspacious ];
}
(builtins.readFile ./frogarized.py);
frogarized_json = polarity: pkgs.runCommand "frogarized-${polarity}.json" { } "${generator} --polarity ${polarity} --output json > $out";
frogarized_nix = polarity: builtins.fromJSON (builtins.readFile (frogarized_json polarity));
in
{
config = {
stylix = {
base16Scheme = frogarized_nix config.stylix.polarity;
# On purpose also enable without a DE because stylix complains otherwise
image = builtins.fetchurl {
url = "https://get.wallhere.com/photo/sunlight-abstract-minimalism-green-simple-circle-light-leaf-wave-material-line-wing-computer-wallpaper-font-close-up-macro-photography-124350.png";
sha256 = "sha256:1zfq3f3v34i45mi72pkfqphm8kbhczsg260xjfl6dbydy91d7y93";
};
};
};
}

View file

@ -1,112 +0,0 @@
import argparse
import json
import colorspacious
import numpy as np
# Original values for the Solarized color scheme,
# created by Ethan Schoonover (https://ethanschoonover.com/solarized/)
SOLARIZED_LAB = np.array(
[
[15, -12, -12],
[20, -12, -12],
[45, -7, -7],
[50, -7, -7],
[60, -6, -3],
[65, -5, -2],
[92, -0, 10],
[97, 0, 10],
[50, 65, 45],
[50, 50, 55],
[60, 10, 65],
[60, -20, 65],
[60, -35, -5],
[55, -10, -45],
[50, 15, -45],
[50, 65, -5],
]
)
# I couldn't get a perfect translation of Solarized L*a*b values into sRGB,
# so here is upstream's translation for reference
SOLARIZED_RGB = np.array(
[
[0, 43, 54],
[7, 54, 66],
[88, 110, 117],
[101, 123, 131],
[131, 148, 150],
[147, 161, 161],
[238, 232, 213],
[253, 246, 227],
[220, 50, 47],
[203, 75, 22],
[181, 137, 0],
[133, 153, 0],
[42, 161, 152],
[38, 139, 210],
[108, 113, 196],
[211, 54, 130],
]
)
# Parse arguments
parser = argparse.ArgumentParser(
description="Generate a base16-theme based derived from Solarized"
)
parser.add_argument("--source", choices=["lab", "rgb"], default="lab")
parser.add_argument("--lightness_factor", type=float, default=1.0)
parser.add_argument("--chroma-factor", type=float, default=1.0)
parser.add_argument("--hue_shift", type=float, default=-75.0)
parser.add_argument("--polarity", choices=["dark", "light"], default="dark")
parser.add_argument(
"--output", choices=["json", "truecolor"], default="truecolor"
)
args = parser.parse_args()
# Convert source to JCh color space
if args.source == "lab":
solarized_jch = colorspacious.cspace_convert(
SOLARIZED_LAB, "CIELab", "JCh"
)
elif args.source == "rgb":
solarized_jch = colorspacious.cspace_convert(
SOLARIZED_RGB, "sRGB255", "JCh"
)
# Build frogarized theme
jch_factor = [args.lightness_factor, args.chroma_factor, 1]
jch_shift = [0, 0, args.hue_shift]
frogarzied_jch = np.vstack(
[solarized_jch[:8] * jch_factor + jch_shift, solarized_jch[8:]]
)
# Convert frogarized to RGB
frogarized_srgb = colorspacious.cspace_convert(
frogarzied_jch, "JCh", "sRGB255"
)
frogarized_rgb = np.uint8(np.rint(np.clip(frogarized_srgb, 0, 255)))
if args.polarity == "light":
frogarized_rgb = np.vstack([frogarized_rgb[7::-1], frogarized_rgb[8:]])
# Output
palette = dict()
for i in range(16):
rgb = frogarized_rgb[i]
r, g, b = rgb
hex = f"#{r:02x}{g:02x}{b:02x}"
palette[f"base{i:02X}"] = hex
if args.output == "truecolor":
print(f"\033[48;2;{r};{g};{b}m{hex}\033[0m") # ]]
# treesitter is silly and will consider brackets in strings
# as indentation, hence the comment above
if args.output == "json":
scheme = palette.copy()
scheme.update(
{
"slug": f"frogarized-{args.polarity}",
"scheme": f"Frogarized {args.polarity.title()}",
"author": "Geoffrey Frogeye (with work from Ethan Schoonover)",
}
)
print(json.dumps(scheme, indent=4))

View file

@ -2,13 +2,13 @@
# MANU Snapper is not able to create the snapshot directory, so you'll need to do this after eventually running the backup script:
# sudo btrfs subvol create /mnt/razmo/$subvolume/.snapshots
let
backup_subvolumes = [ "nixos" "home.rapido" "home.nixos" ];
backup_subvolumes = [ "nixos" "home.rapido" ];
backup_app = pkgs.writeShellApplication {
name = "backup-subvolume";
runtimeInputs = with pkgs; [ coreutils btrfs-progs ];
text = builtins.readFile ./backup.sh;
};
snapper_subvolumes = [ "nixos" "home.rapido" "home.razmo" "home.nixos" ];
snapper_subvolumes = [ "nixos" "home.rapido" "home.razmo" ];
in
{
services =

View file

@ -1,71 +0,0 @@
{ pkgs, lib, config, ... }:
let
zytemp_mqtt_src = pkgs.fetchFromGitHub {
owner = "patrislav1";
repo = "zytemp_mqtt";
rev = "a6be5e3082e1e10dee435cfb9643fb13e9a71c34"; # PR that adds humidity
sha256 = "sha256-cMWDi20isnbB6jlMzut7YyYB4te4bVFYXSgCEQWQnts=";
};
zytemp_mqtt = pkgs.python3Packages.buildPythonPackage
rec {
name = "zytemp_mqtt";
src = zytemp_mqtt_src;
propagatedBuildInputs = with pkgs.python3Packages; [ hidapi paho-mqtt pyaml ];
};
usb_zytemp_udev = pkgs.stdenv.mkDerivation {
pname = "usb-zytemp-udev-rules";
version = "unstable-2023-05-24";
src = zytemp_mqtt_src;
dontConfigure = true;
dontBuild = true;
dontFixup = true;
installPhase = ''
mkdir -p $out/lib/udev/rules.d
cp udev/90-usb-zytemp-permissions.rules $out/lib/udev/rules.d/90-usb-zytemp.rules
'';
};
mqtt_host = "192.168.7.53"; # Ludwig
in
{
config = {
environment.etc."zytempmqtt/config.yaml".text = lib.generators.toYAML { } {
decrypt = true;
mqtt_host = mqtt_host;
friendly_name = "Desk sensor";
};
services.udev.packages = [ usb_zytemp_udev ];
systemd = {
services.zytemp_mqtt = {
description = "Forward zyTemp CO2 sensor to MQTT";
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${zytemp_mqtt}/bin/zytempmqtt";
# Hardening (hapazardeous)
CapabilityBoundingSet = "";
DynamicUser = true;
LockPersonality = true;
MemoryDenyWriteExecute = false;
NoNewPrivileges = true;
PrivateTmp = true;
PrivateUsers = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
RemoveIPC = true;
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
SystemCallFilter = [ "@system-service" "~@privileged" "~@resouces" ];
UMask = "0077";
};
};
};
};
}

View file

@ -1,17 +0,0 @@
{ pkgs, lib, config, ... }:
{
config = {
services.beesd.filesystems = {
razmo = {
spec = "/mnt/razmo";
hashTableSizeMB = 512; # Recommended for 1 TiB, ×2 for compression, x2 for time
extraOptions = [ "--loadavg-target" "10" ]; # This one is tame
};
rapido = {
spec = "/mnt/rapido";
hashTableSizeMB = 128; # 4 times smaller disk, 4 times smaller hashtable?
extraOptions = [ "--loadavg-target" "7.5" ]; # This one can slow things down
};
};
};
}

View file

@ -1,16 +0,0 @@
{ pkgs, lib, config, ... }:
{
config = {
networking.hostName = "curacao";
};
imports = [
# ./backup
./co2meter
# ./dedup
./disko.nix
./features.nix
./hardware.nix
./homeautomation
./webcam
];
}

View file

@ -1,4 +1,4 @@
{ pkgs, lib, config, ... }:
{ passwordFile ? "/should_not_be_needed_in_this_context", ... }:
# TODO Find a way to use keys in filesystem
# TODO Not relatime everywhere, thank you
# TODO Default options
@ -10,10 +10,8 @@ let
"space_cache"
];
btrfs_args_ssd = btrfs_args_hdd ++ [ "ssd" ];
passwordFile = "/tmp/dotfiles_${config.networking.hostName}_password";
in
{
boot.loader.efi.efiSysMountPoint = config.disko.devices.disk.razmo.content.partitions.esp.content.mountpoint;
disko.devices = {
disk = {
razmo = {
@ -34,6 +32,7 @@ in
# hibernation image is saved. That's what I'm doing with Arch,
# but I'm setting resume=, should test if it actually works?
# Untranslated options from /etc/crypttab: swap,cipher=aes-xts-plain64,size=256
# Untranslated options from /etc/fstab: defaults,pri=100
};
};
nixosboot = {
@ -159,6 +158,10 @@ in
mountpoint = "/mnt/rapido";
mountOptions = btrfs_args_ssd;
subvolumes = {
archlinux = {
mountpoint = "/mnt/old";
mountOptions = btrfs_args_ssd;
};
# Should be temporary, to make sure we can revert to Arch anytime
"home.nixos" = {
mountpoint = "/home";
@ -184,9 +187,4 @@ in
};
};
};
services.btrfs.autoScrub = {
enable = true;
fileSystems = [ "/mnt/razmo" "/mnt/rapido" ];
# TODO Should be generable from disko config, right?
};
}

View file

@ -1,13 +0,0 @@
{ ... }:
{
frogeye = {
desktop = {
xorg = true;
};
dev = {
docker = true;
};
extra = true;
gaming = true;
};
}

View file

@ -1,36 +1,17 @@
{ pkgs, lib, config, nixos-hardware, ... }:
{ lib, ... }:
{
config = {
# UEFI works here, and variables can be touched
boot.loader = {
efi.canTouchEfiVariables = lib.mkDefault true;
grub = {
enable = true;
efiSupport = true;
device = "nodev"; # Don't install on MBR
# TODO Maybe we could? In case the HDD doesn't boot anymore?
};
};
hardware.cpu.intel.updateMicrocode = true;
frogeye.desktop = {
x11_screens = [
"HDMI-1-3"
"DVI-I-2-1"
];
maxVideoHeight = 1440;
numlock = true;
phasesBrightness = {
enable = true;
jour = "40000";
crepuscule = "10000";
nuit = "1";
};
};
# Needs prefetched binary blobs, see https://nixos.wiki/wiki/Displaylink
services.xserver.videoDrivers = [ "displaylink" "modesetting" ];
# TODO See if nvidia and DL can work together.
};
imports = [
nixos-hardware.nixosModules.dell-g3-3779
<nixos-hardware/dell/g3/3779>
];
# UEFI works here, and variables can be touched
boot.loader = {
efi.canTouchEfiVariables = lib.mkDefault true;
grub = {
enable = true;
efiSupport = true;
device = "nodev"; # Don't install on MBR
# TODO Maybe we could? In case the HDD doesn't boot anymore?
};
};
}

View file

@ -1,13 +0,0 @@
{ pkgs, lib, config, ... }:
{
config = {
networking = {
# Allow mpd control from home assistant and phone
firewall.extraCommands = ''
iptables -A nixos-fw -p tcp -m tcp --dport 6600 -s 192.168.7.53 -j nixos-fw-accept
iptables -A nixos-fw -p tcp -m tcp --dport 6600 -s 192.168.7.92 -j nixos-fw-accept
'';
interfaces.enp3s0.wakeOnLan.enable = true;
};
};
}

22
curacao/options.nix Normal file
View file

@ -0,0 +1,22 @@
{ ... }:
{
frogeye = {
desktop = {
xorg = true;
x11_screens = [ "HDMI-1-0" "eDP-1" ];
maxVideoHeight = 1440;
numlock = true;
phasesBrightness = {
enable = true;
jour = "40000";
crepuscule = "10000";
nuit = "1";
};
};
dev = {
docker = true;
};
extra = true;
gaming = true;
};
}

18
curacao/os.nix Normal file
View file

@ -0,0 +1,18 @@
{ ... }:
{
imports = [
../os
./options.nix
./hardware.nix
./dk.nix
./backup
];
networking.hostName = "curacao";
boot = {
initrd.luks.reusePassphrases = true;
loader = {
efi.efiSysMountPoint = "/efi";
};
};
}

View file

@ -1,13 +0,0 @@
{ pkgs, lib, config, ... }:
{
config = {
boot.loader.efi.canTouchEfiVariables = false;
disko.devices.disk."${config.networking.hostName}".device = "/dev/disk/by-id/usb-Kingston_DataTraveler_3.0_E0D55EA57414F510489F0F1A-0:0";
networking.hostName = "curacao-usb";
};
imports = [
../common/disko/single_uefi_btrfs.nix
./features.nix
./hardware.nix
];
}

View file

@ -1,14 +0,0 @@
{ pkgs, lib, config, ... }:
{
config = {
# TODO This should install cameractrls, but it seems like it's not easy to install.
# In the meantime, we install Flatpak and do:
# flatpak run hu.irl.cameractrls
services.flatpak.enable = true;
xdg.portal = {
config.common.default = "*";
enable = true;
extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
};
};
}

12
curacao_test/hm.nix Normal file
View file

@ -0,0 +1,12 @@
{ ... }:
{
imports = [
../hm
../curacao/options.nix
];
home.username = "gnix";
home.homeDirectory = "/home/gnix";
frogeye.desktop.nixGLIntel = true;
}

2
curacao_usb/dk.nix Normal file
View file

@ -0,0 +1,2 @@
{ ... } @ args:
import ../dk/single_uefi_btrfs.nix (args // { id = "usb-Kingston_DataTraveler_3.0_E0D55EA57414F510489F0F1A-0:0"; name = "curacao_usb"; })

22
curacao_usb/os.nix Normal file
View file

@ -0,0 +1,22 @@
{ pkgs, config, ... }:
{
imports = [
../os
../curacao/options.nix
../curacao/hardware.nix
./dk.nix
];
networking.hostName = "curacao_usb";
# It's a removable drive, so no touching EFI vars
# (quite a lot of stuff to set for that!)
boot.loader = {
efi.canTouchEfiVariables = false;
grub = {
efiInstallAsRemovable = true;
device = "nodev";
};
};
}

View file

@ -1,12 +1,10 @@
{ pkgs, lib, config, ... }:
let
passwordFile = "/tmp/dotfiles_${config.networking.hostName}_password";
in
{ id, name, passwordFile ? "/should_not_be_needed_in_this_context", ... }:
{
disko.devices = {
disk = {
"${config.networking.hostName}" = {
"${name}" = {
type = "disk";
device = "/dev/disk/by-id/${id}";
content = {
type = "gpt";
partitions = {
@ -27,7 +25,7 @@ in
size = "100%";
content = {
type = "luks";
name = "${config.networking.hostName}";
name = "${name}";
passwordFile = passwordFile;
settings = {
# Not having SSDs die fast is more important than crypto

55
ensure_nix.sh Executable file
View file

@ -0,0 +1,55 @@
#!/usr/bin/env bash
# Runs the command given in a Nix environment, and create it if it doesn't exist.
# Useful for environments where nix isn't installed / you do not have root access
# If you need a fresh slate:
# chmod +w .nix -R
# rm -rf .nix .nix-defexpr .nix-profile .config/nix .local/state/nix .local/share/nix .cache/nix
set -euo pipefail
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
if [ ! -d /nix ]
then
# Doesn't support architectures other than x86_64
NIX_USER_CHROOT_URL=https://github.com/nix-community/nix-user-chroot/releases/download/1.2.2/nix-user-chroot-bin-1.2.2-x86_64-unknown-linux-musl
NIX_USER_CHROOT_SHA256SUM=e11aff604bb8d3ffd1d9c0c68cd636816d7eb8da540de18ee3a41ccad7ac0972
nix_user_chroot="$HOME/.local/bin/nix-user-chroot"
mkdir -p "$(dirname "$nix_user_chroot")"
nix_directory="$HOME/.nix"
mkdir -p "$nix_directory"
if [ ! -x "$nix_user_chroot" ] || ! echo "$NIX_USER_CHROOT_SHA256SUM $nix_user_chroot" | sha256sum --check --status
then
wget "$NIX_USER_CHROOT_URL" -O "$nix_user_chroot"
echo "$NIX_USER_CHROOT_SHA256SUM $nix_user_chroot" | sha256sum --check --status
chmod +x "$nix_user_chroot"
fi
exec "$nix_user_chroot" "$nix_directory" "$0" "$@"
exit 1
fi
nix_profile_path="$HOME/.nix-profile/etc/profile.d/nix.sh"
if [ ! -f "$nix_profile_path" ]
then
NIX_INSTALLER_URL=https://releases.nixos.org/nix/nix-2.19.2/install
NIX_INSTALLER_SHA256SUM=435f0d7e11f7c7dffeeab0ec9cc55723f6d3c03352379d785633cf4ddb5caf90
nix_installer="$(mktemp)"
wget "$NIX_INSTALLER_URL" -O "$nix_installer"
echo "$NIX_INSTALLER_SHA256SUM $nix_installer" | sha256sum --check --status
chmod +x "$nix_installer"
"$nix_installer" --no-daemon --yes --no-channel-add --no-modify-profile
fi
. "$nix_profile_path"
"${SCRIPT_DIR}/add_channels.sh"
exec "$@"

View file

@ -1,757 +0,0 @@
{
"nodes": {
"base16": {
"inputs": {
"fromYaml": "fromYaml"
},
"locked": {
"lastModified": 1689633990,
"narHash": "sha256-iwvQg2Vx0IIDWZaKo8Xmzxlv1YPHg+Kp/QSv8dRv0RY=",
"owner": "SenchoPens",
"repo": "base16.nix",
"rev": "dddf2e1c04845d43c89a8e9e37d574519649a404",
"type": "github"
},
"original": {
"owner": "SenchoPens",
"repo": "base16.nix",
"type": "github"
}
},
"base16-alacritty": {
"flake": false,
"locked": {
"lastModified": 1703982197,
"narHash": "sha256-TNxKbwdiUXGi4Z4chT72l3mt3GSvOcz6NZsUH8bQU/k=",
"owner": "aarowill",
"repo": "base16-alacritty",
"rev": "c95c200b3af739708455a03b5d185d3d2d263c6e",
"type": "github"
},
"original": {
"owner": "aarowill",
"repo": "base16-alacritty",
"type": "github"
}
},
"base16-alacritty-yaml": {
"flake": false,
"locked": {
"lastModified": 1674275109,
"narHash": "sha256-Adwx9yP70I6mJrjjODOgZJjt4OPPe8gJu7UuBboXO4M=",
"owner": "aarowill",
"repo": "base16-alacritty",
"rev": "63d8ae5dfefe5db825dd4c699d0cdc2fc2c3eaf7",
"type": "github"
},
"original": {
"owner": "aarowill",
"repo": "base16-alacritty",
"rev": "63d8ae5dfefe5db825dd4c699d0cdc2fc2c3eaf7",
"type": "github"
}
},
"base16-fish": {
"flake": false,
"locked": {
"lastModified": 1622559957,
"narHash": "sha256-PebymhVYbL8trDVVXxCvZgc0S5VxI7I1Hv4RMSquTpA=",
"owner": "tomyun",
"repo": "base16-fish",
"rev": "2f6dd973a9075dabccd26f1cded09508180bf5fe",
"type": "github"
},
"original": {
"owner": "tomyun",
"repo": "base16-fish",
"type": "github"
}
},
"base16-foot": {
"flake": false,
"locked": {
"lastModified": 1696725948,
"narHash": "sha256-65bz2bUL/yzZ1c8/GQASnoiGwaF8DczlxJtzik1c0AU=",
"owner": "tinted-theming",
"repo": "base16-foot",
"rev": "eedbcfa30de0a4baa03e99f5e3ceb5535c2755ce",
"type": "github"
},
"original": {
"owner": "tinted-theming",
"repo": "base16-foot",
"type": "github"
}
},
"base16-helix": {
"flake": false,
"locked": {
"lastModified": 1696727917,
"narHash": "sha256-FVrbPk+NtMra0jtlC5oxyNchbm8FosmvXIatkRbYy1g=",
"owner": "tinted-theming",
"repo": "base16-helix",
"rev": "dbe1480d99fe80f08df7970e471fac24c05f2ddb",
"type": "github"
},
"original": {
"owner": "tinted-theming",
"repo": "base16-helix",
"type": "github"
}
},
"base16-kitty": {
"flake": false,
"locked": {
"lastModified": 1665001328,
"narHash": "sha256-aRaizTYPpuWEcvoYE9U+YRX+Wsc8+iG0guQJbvxEdJY=",
"owner": "kdrag0n",
"repo": "base16-kitty",
"rev": "06bb401fa9a0ffb84365905ffbb959ae5bf40805",
"type": "github"
},
"original": {
"owner": "kdrag0n",
"repo": "base16-kitty",
"type": "github"
}
},
"base16-tmux": {
"flake": false,
"locked": {
"lastModified": 1696725902,
"narHash": "sha256-wDPg5elZPcQpu7Df0lI5O8Jv4A3T6jUQIVg63KDU+3Q=",
"owner": "tinted-theming",
"repo": "base16-tmux",
"rev": "c02050bebb60dbb20cb433cd4d8ce668ecc11ba7",
"type": "github"
},
"original": {
"owner": "tinted-theming",
"repo": "base16-tmux",
"type": "github"
}
},
"base16-vim": {
"flake": false,
"locked": {
"lastModified": 1663659192,
"narHash": "sha256-uJvaYYDMXvoo0fhBZUhN8WBXeJ87SRgof6GEK2efFT0=",
"owner": "chriskempson",
"repo": "base16-vim",
"rev": "3be3cd82cd31acfcab9a41bad853d9c68d30478d",
"type": "github"
},
"original": {
"owner": "chriskempson",
"repo": "base16-vim",
"type": "github"
}
},
"disko": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1715217706,
"narHash": "sha256-yEB5SEHc+o3WJpUPw455OdLy9A+gffvCJX8DZ7NCkuo=",
"owner": "nix-community",
"repo": "disko",
"rev": "8eb1b315eef89f3bdc5c9814d1b207c6d64f0046",
"type": "github"
},
"original": {
"id": "disko",
"type": "indirect"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1710146030,
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1710146030,
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_3": {
"inputs": {
"systems": "systems_3"
},
"locked": {
"lastModified": 1701680307,
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_4": {
"inputs": {
"systems": "systems_4"
},
"locked": {
"lastModified": 1685518550,
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flakey-profile": {
"locked": {
"lastModified": 1712898590,
"narHash": "sha256-FhGIEU93VHAChKEXx905TSiPZKga69bWl1VB37FK//I=",
"owner": "lf-",
"repo": "flakey-profile",
"rev": "243c903fd8eadc0f63d205665a92d4df91d42d9d",
"type": "github"
},
"original": {
"owner": "lf-",
"repo": "flakey-profile",
"type": "github"
}
},
"fromYaml": {
"flake": false,
"locked": {
"lastModified": 1689549921,
"narHash": "sha256-iX0pk/uB019TdBGlaJEWvBCfydT6sRq+eDcGPifVsCM=",
"owner": "SenchoPens",
"repo": "fromYaml",
"rev": "11fbbbfb32e3289d3c631e0134a23854e7865c84",
"type": "github"
},
"original": {
"owner": "SenchoPens",
"repo": "fromYaml",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"nixvim",
"pre-commit-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1660459072,
"narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1714043624,
"narHash": "sha256-Xn2r0Jv95TswvPlvamCC46wwNo8ALjRCMBJbGykdhcM=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "86853e31dc1b62c6eeed11c667e8cdd0285d4411",
"type": "github"
},
"original": {
"id": "home-manager",
"ref": "release-23.11",
"type": "indirect"
}
},
"home-manager_2": {
"inputs": {
"nixpkgs": [
"stylix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1700847865,
"narHash": "sha256-uWaOIemGl9LF813MW0AEgCBpKwFo2t1Wv3BZc6e5Frw=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "8cedd63eede4c22deb192f1721dd67e7460e1ebe",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"lix": {
"flake": false,
"locked": {
"lastModified": 1714955862,
"narHash": "sha256-REWlo2RYHfJkxnmZTEJu3Cd/2VM+wjjpPy7Xi4BdDTQ=",
"ref": "refs/tags/2.90-beta.1",
"rev": "b6799ab0374a8e1907a48915d3187e07da41d88c",
"revCount": 15501,
"type": "git",
"url": "https://git@git.lix.systems/lix-project/lix"
},
"original": {
"ref": "refs/tags/2.90-beta.1",
"type": "git",
"url": "https://git@git.lix.systems/lix-project/lix"
}
},
"lix-module": {
"inputs": {
"flake-utils": "flake-utils_2",
"flakey-profile": "flakey-profile",
"lix": [
"lix"
],
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1715353627,
"narHash": "sha256-bt/KZsPUlQV1lOZU8vM3QT/05jHftCz88tA9+bXk83s=",
"ref": "fix-prefetch-npm-deps",
"rev": "1cb0b0434d83719d73946b4516475e5ca31a2f2d",
"revCount": 76,
"type": "git",
"url": "https://git.lix.systems/lix-project/nixos-module"
},
"original": {
"ref": "fix-prefetch-npm-deps",
"type": "git",
"url": "https://git.lix.systems/lix-project/nixos-module"
}
},
"nix-formatter-pack": {
"inputs": {
"nixpkgs": [
"nix-on-droid",
"nixpkgs"
],
"nmd": "nmd",
"nmt": "nmt"
},
"locked": {
"lastModified": 1666720474,
"narHash": "sha256-iWojjDS1D19zpeZXbBdjWb9MiKmVVFQCqtJmtTXgPx8=",
"owner": "Gerschtli",
"repo": "nix-formatter-pack",
"rev": "14876cc8fe94a3d329964ecb073b4c988c7b61f5",
"type": "github"
},
"original": {
"owner": "Gerschtli",
"repo": "nix-formatter-pack",
"type": "github"
}
},
"nix-on-droid": {
"inputs": {
"home-manager": [
"home-manager"
],
"nix-formatter-pack": "nix-formatter-pack",
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-for-bootstrap": "nixpkgs-for-bootstrap",
"nmd": "nmd_2"
},
"locked": {
"lastModified": 1688144254,
"narHash": "sha256-8KL1l/7eP2Zm1aJjdVaSOk0W5kTnJo9kcgW03gqWuiI=",
"owner": "nix-community",
"repo": "nix-on-droid",
"rev": "2301e01d48c90b60751005317de7a84a51a87eb6",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "release-23.05",
"repo": "nix-on-droid",
"type": "github"
}
},
"nixos-hardware": {
"locked": {
"lastModified": 1715148395,
"narHash": "sha256-lRxjTxY3103LGMjWdVqntKZHhlmMX12QUjeFrQMmGaE=",
"owner": "NixOS",
"repo": "nixos-hardware",
"rev": "a4e2b7909fc1bdf30c30ef21d388fde0b5cdde4a",
"type": "github"
},
"original": {
"id": "nixos-hardware",
"type": "indirect"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1715106579,
"narHash": "sha256-gZMgKEGiK6YrwGBiccZ1gemiUwjsZ1Zv49KYOgmX2fY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8be0d8a1ed4f96d99b09aa616e2afd47acc3da89",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-23.11",
"type": "indirect"
}
},
"nixpkgs-for-bootstrap": {
"locked": {
"lastModified": 1686921029,
"narHash": "sha256-J1bX9plPCFhTSh6E3TWn9XSxggBh/zDD4xigyaIQBy8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c7ff1b9b95620ce8728c0d7bd501c458e6da9e04",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c7ff1b9b95620ce8728c0d7bd501c458e6da9e04",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1685801374,
"narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c37ca420157f4abc31e26f436c1145f8951ff373",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-23.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixvim": {
"inputs": {
"flake-utils": "flake-utils_3",
"nixpkgs": [
"nixpkgs"
],
"pre-commit-hooks": "pre-commit-hooks"
},
"locked": {
"lastModified": 1705700164,
"narHash": "sha256-YAWtzc+5KDOHDGz/NBB7ysIusXbYYKtsbDOsRhSWKYk=",
"owner": "GeoffreyFrogeye",
"repo": "nixvim",
"rev": "2e5f7781fccba0472277cad5d383d10d50772234",
"type": "github"
},
"original": {
"owner": "GeoffreyFrogeye",
"ref": "frogeye-23.11",
"repo": "nixvim",
"type": "github"
}
},
"nmd": {
"flake": false,
"locked": {
"lastModified": 1666190571,
"narHash": "sha256-Z1hc7M9X6L+H83o9vOprijpzhTfOBjd0KmUTnpHAVjA=",
"owner": "rycee",
"repo": "nmd",
"rev": "b75d312b4f33bd3294cd8ae5c2ca8c6da2afc169",
"type": "gitlab"
},
"original": {
"owner": "rycee",
"repo": "nmd",
"type": "gitlab"
}
},
"nmd_2": {
"flake": false,
"locked": {
"lastModified": 1666190571,
"narHash": "sha256-Z1hc7M9X6L+H83o9vOprijpzhTfOBjd0KmUTnpHAVjA=",
"owner": "rycee",
"repo": "nmd",
"rev": "b75d312b4f33bd3294cd8ae5c2ca8c6da2afc169",
"type": "gitlab"
},
"original": {
"owner": "rycee",
"repo": "nmd",
"type": "gitlab"
}
},
"nmt": {
"flake": false,
"locked": {
"lastModified": 1648075362,
"narHash": "sha256-u36WgzoA84dMVsGXzml4wZ5ckGgfnvS0ryzo/3zn/Pc=",
"owner": "rycee",
"repo": "nmt",
"rev": "d83601002c99b78c89ea80e5e6ba21addcfe12ae",
"type": "gitlab"
},
"original": {
"owner": "rycee",
"repo": "nmt",
"type": "gitlab"
}
},
"nur": {
"locked": {
"lastModified": 1715283921,
"narHash": "sha256-QrSRlqvGibusEgrTjxKO+1gA1UZtJ81zq1srqQkB+Us=",
"owner": "nix-community",
"repo": "NUR",
"rev": "69781c45be9db020bec046adb4279bff946c1014",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "NUR",
"type": "github"
}
},
"pre-commit-hooks": {
"inputs": {
"flake-compat": "flake-compat",
"flake-utils": "flake-utils_4",
"gitignore": "gitignore",
"nixpkgs": [
"nixvim",
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1700922917,
"narHash": "sha256-ej2fch/T584b5K9sk1UhmZF7W6wEfDHuoUYpFN8dtvM=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "e5ee5c5f3844550c01d2131096c7271cec5e9b78",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"root": {
"inputs": {
"disko": "disko",
"flake-utils": "flake-utils",
"home-manager": "home-manager",
"lix": "lix",
"lix-module": "lix-module",
"nix-on-droid": "nix-on-droid",
"nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs",
"nixvim": "nixvim",
"nur": "nur",
"stylix": "stylix",
"unixpkgs": "unixpkgs"
}
},
"stylix": {
"inputs": {
"base16": "base16",
"base16-alacritty": "base16-alacritty",
"base16-alacritty-yaml": "base16-alacritty-yaml",
"base16-fish": "base16-fish",
"base16-foot": "base16-foot",
"base16-helix": "base16-helix",
"base16-kitty": "base16-kitty",
"base16-tmux": "base16-tmux",
"base16-vim": "base16-vim",
"flake-compat": "flake-compat_2",
"home-manager": "home-manager_2",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1705668784,
"narHash": "sha256-U/1Qol9H5nb8FtWSXSiHY8T4Y7TOIo7NHuqe4uuiBec=",
"owner": "danth",
"repo": "stylix",
"rev": "a9e3ce064a778b386fb88fb152c02ae95aa2cbd2",
"type": "github"
},
"original": {
"owner": "danth",
"ref": "release-23.11",
"repo": "stylix",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_3": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_4": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"unixpkgs": {
"locked": {
"lastModified": 1715037484,
"narHash": "sha256-OUt8xQFmBU96Hmm4T9tOWTu4oCswCzoVl+pxSq/kiFc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ad7efee13e0d216bf29992311536fce1d3eefbef",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
}
},
"root": "root",
"version": 7
}

148
flake.nix
View file

@ -1,148 +0,0 @@
{
description = "Geoffrey Frogeye's base configurations";
inputs = {
# Package manager
lix = {
url = "git+https://git@git.lix.systems/lix-project/lix?ref=refs/tags/2.90-beta.1";
flake = false;
};
lix-module = {
url = "git+https://git.lix.systems/lix-project/nixos-module?ref=fix-prefetch-npm-deps";
inputs = {
lix.follows = "lix";
nixpkgs.follows = "nixpkgs";
};
};
# Packages
nixpkgs.url = "nixpkgs/nixos-23.11";
unixpkgs.url = "nixpkgs";
# OS
disko = {
url = "disko";
inputs.nixpkgs.follows = "nixpkgs";
};
nixos-hardware.url = "nixos-hardware";
# NOD
nix-on-droid = {
url = "github:nix-community/nix-on-droid/release-23.05"; # No 23.11 :(
inputs.nixpkgs.follows = "nixpkgs";
inputs.home-manager.follows = "home-manager";
};
# HM
home-manager = {
url = "home-manager/release-23.11";
inputs.nixpkgs.follows = "nixpkgs";
};
stylix = {
url = "github:danth/stylix/release-23.11";
inputs.nixpkgs.follows = "nixpkgs";
};
nixvim = {
url = "github:GeoffreyFrogeye/nixvim/frogeye-23.11";
# 24.05 Ensure merged: https://github.com/nix-community/nixvim/pull/953
# url = "github:nix-community/nixvim";
inputs.nixpkgs.follows = "nixpkgs";
};
nur.url = "github:nix-community/NUR";
# Local
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, unixpkgs, disko, nix-on-droid, flake-utils, ... }@attrs:
# Machine independant outputs
let
nixpkgsConfig = {
config = {
allowUnfree = true;
};
overlays = [
(final: prev: { unstable = unixpkgs.legacyPackages.${prev.system}.pkgs; })
];
};
homeManagerConfig = {
sharedModules = [ self.homeManagerModules.dotfiles ];
extraSpecialArgs = attrs;
};
lib = {
nixosSystem = { system, modules ? [ ] }: nixpkgs.lib.nixosSystem {
inherit system;
specialArgs = attrs;
modules = modules ++ [
self.nixosModules.dotfiles
{
nixpkgs = nixpkgsConfig;
home-manager = homeManagerConfig;
}
];
};
nixOnDroidConfiguration = { modules ? [ ] }: nix-on-droid.lib.nixOnDroidConfiguration {
pkgs = import nixpkgs (nixpkgsConfig // {
system = "aarch64-linux"; # nod doesn't support anything else
});
modules = modules ++ [
self.nixOnDroidModules.dotfiles
{
home-manager = homeManagerConfig;
}
];
};
flakeTools = { self }: flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
{
apps = {
disko = {
type = "app";
program = "${disko.packages.${system}.default}/bin/disko";
};
nixos-generate-config = {
type = "app";
program = "${pkgs.nixos-install-tools}/bin/nixos-generate-config";
};
nixos-install = {
type = "app";
program = "${pkgs.nixos-install-tools}/bin/nixos-install";
};
nixos-rebuild = {
type = "app";
program = "${pkgs.nixos-rebuild}/bin/nixos-rebuild";
};
repl = {
type = "app";
program = "${pkgs.writeShellScript "vivarium-repl" ''
${pkgs.nix}/bin/nix repl --expr 'let flake = builtins.getFlake "${self}"; in flake // flake.nixosConfigurations // rec { pkgs = import ${nixpkgs} {}; lib = pkgs.lib; }'
''}";
};
};
}
);
};
in
{
# Reusable configurations
inherit lib;
nixosModules.dotfiles.imports = [ ./os ];
nixOnDroidModules.dotfiles.imports = [ ./nod ];
homeManagerModules.dotfiles.imports = [ ./hm ];
# Actual configurations
nixosConfigurations.curacao = lib.nixosSystem {
system = "x86_64-linux";
modules = [ ./curacao ];
};
nixosConfigurations.curacao-usb = lib.nixosSystem {
system = "x86_64-linux";
modules = [ ./curacao/usb.nix ];
};
nixosConfigurations.pindakaas = lib.nixosSystem {
system = "aarch64-linux";
modules = [ ./pindakaas ];
};
nixosConfigurations.pindakaas-sd = lib.nixosSystem {
system = "aarch64-linux";
modules = [ ./pindakaas/sd.nix ];
};
nixOnDroidConfigurations.sprinkles = lib.nixOnDroidConfiguration { };
} // (lib.flakeTools { inherit self; });
}

6
full/README.md Normal file
View file

@ -0,0 +1,6 @@
# full profile
Fake configuration that contains everything I could ever need,
used for debugging.
Can't build a full system due to not having a filesystem / bootloader configuration,
build as a VM (without bootloader).

17
full/options.nix Normal file
View file

@ -0,0 +1,17 @@
{ ... }:
{
frogeye = {
desktop.xorg = true;
dev = {
ansible = true;
c = true;
docker = true;
fpga = true;
perl = true;
php = true;
python = true;
};
extra = true;
gaming = true;
};
}

10
full/os.nix Normal file
View file

@ -0,0 +1,10 @@
{ ... }:
{
imports = [
../os
./options.nix
];
# Create a different disk image depending on the architecture
networking.hostName = "${builtins.currentSystem}";
}

View file

@ -1,108 +0,0 @@
{ pkgs, config, lib, ... }:
let
mkUserJs = with lib; prefs: extraPrefs: ''
// Generated by Geoffrey's dotfiles.
${concatStrings (mapAttrsToList (name: value: ''
user_pref("${name}", ${builtins.toJSON value});
'') prefs)}
${extraPrefs}
'';
toThunderbirdCalendar = account:
let
id = builtins.hashString "sha256" account.name;
thunderbird = config.frogeye.accounts.calendar.accounts.${account.name};
in
{
"calendar.registry.${id}.cache.enabled" = thunderbird.offlineSupport; # TODO Check this actually corresponds
"calendar.registry.${id}.color" = thunderbird.color;
"calendar.registry.${id}.forceEmailScheduling" = thunderbird.clientSideEmailScheduling;
"calendar.registry.${id}.imip.identity.key" = "id_${builtins.hashString "sha256" thunderbird.email}";
"calendar.registry.${id}.name" = account.name;
"calendar.registry.${id}.readOnly" = thunderbird.readOnly;
"calendar.registry.${id}.refreshInterval" = builtins.toString thunderbird.refreshInterval;
"calendar.registry.${id}.suppressAlarms" = !thunderbird.showReminders; # TODO Check this actually corresponds
"calendar.registry.${id}.type" = account.remote.type; # TODO Check and validate supported types
"calendar.registry.${id}.uri" = account.remote.url;
"calendar.registry.${id}.username" = account.remote.userName;
# Unimplemented
"calendar.registry.${id}.notifications.times" = "";
# Unknown
# "calendar.registry.${id}.calendar-main-in-composite" = true;
};
in
{
config = {
programs.aerc = {
enable = true;
extraConfig.general.unsafe-accounts-conf = true;
};
programs.thunderbird = {
enable = config.frogeye.desktop.xorg;
profiles.hm = {
isDefault = true;
withExternalGnupg = true;
extraConfig = mkUserJs
(lib.attrsets.mergeAttrsList (
# Add calendar config
(lib.mapAttrsToList (name: account: (toThunderbirdCalendar account)) config.accounts.calendar.accounts) ++
# Add config for every identity (kinda)
(lib.mapAttrsToList
(name: account: ({
# UPST Make signature be used in Thunderbird
"mail.identity.id_${builtins.hashString "sha256" account.address}.htmlSigText" = account.signature.text;
"mail.identity.id_${builtins.hashString "sha256" account.address}.compose_html" = false;
}))
config.accounts.email.accounts) ++
# General settings
[{
"mail.pane_config.dynamic" = 0;
"intl.date_time.pattern_override.date_short" = "yyyy-MM-dd";
}]
)) "";
};
};
};
# UPST Thunderbird-specific options (should be named so), to be included in HM Thunderbird module
options = {
frogeye.accounts.calendar.accounts = lib.mkOption {
default = { };
type = lib.types.attrsOf (lib.types.submodule ({ config, name, ... }: {
# TODO Set defaults as Thunderbird sets it
options = {
color = lib.mkOption {
type = lib.types.str;
default = "#5277c3";
};
refreshInterval = lib.mkOption {
type = lib.types.int;
default = 0; # 0 = Manual
};
readOnly = lib.mkOption {
type = lib.types.bool;
default = false;
};
showReminders = lib.mkOption {
type = lib.types.bool;
default = true;
};
offlineSupport = lib.mkOption {
type = lib.types.bool;
default = true;
};
email = lib.mkOption {
type = lib.types.str;
# TODO Nullable
# TODO Ensure it actually matches an email identity
};
clientSideEmailScheduling = lib.mkOption {
type = lib.types.bool;
default = false;
};
};
}));
};
};
}

View file

@ -1,36 +0,0 @@
# Light theme during the day, dark theme during the night (not automatic)
{ pkgs, lib, config, ... }:
let
phases = [
{ command = "jour"; polarity = "light"; }
{ command = "crepuscule"; polarity = "dark"; }
{ command = "nuit"; polarity = "dark"; }
];
phasesBrightness = config.frogeye.desktop.phasesBrightness;
in
{
config = {
home.packages = map
(phase: (pkgs.writeShellApplication {
name = "${phase.command}";
runtimeInputs = [ pkgs.brightnessctl ];
text = (lib.optionalString phasesBrightness.enable ''
brightnessctl set ${builtins.getAttr phase.command phasesBrightness}
'') + ''
switch="/nix/var/nix/profiles/system/specialisation/${phase.polarity}/bin/switch-to-configuration"
if [ -x "$switch" ]
then
# In two steps to get the visual changes slightly earlier
sudo "$switch" test
sudo "$switch" boot
fi
'';
})
)
phases;
xsession.windowManager.i3.config.keybindings = {
"XF86MonBrightnessUp" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set +5%";
"XF86MonBrightnessDown" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set 5%-";
};
};
}

View file

@ -1,137 +1,389 @@
{ pkgs, config, lib, ... }:
let
direnv = {
# Environment variables making programs stay out of $HOME, but also needing we create a directory for them
CARGOHOME = "${config.xdg.cacheHome}/cargo"; # There are config in there that we can version if one want
CCACHE_DIR = "${config.xdg.cacheHome}/ccache"; # The config file alone seems to be not enough
DASHT_DOCSETS_DIR = "${config.xdg.cacheHome}/dash_docsets";
GOPATH = "${config.xdg.cacheHome}/go";
GRADLE_USER_HOME = "${config.xdg.cacheHome}/gradle";
MIX_ARCHIVES = "${config.xdg.cacheHome}/mix/archives";
MONO_GAC_PREFIX = "${config.xdg.cacheHome}/mono";
npm_config_cache = "${config.xdg.cacheHome}/npm";
PARALLEL_HOME = "${config.xdg.cacheHome}/parallel";
TERMINFO = "${config.xdg.configHome}/terminfo";
WINEPREFIX = "${config.xdg.stateHome}/wineprefix/default";
YARN_CACHE_FOLDER = "${config.xdg.cacheHome}/yarn";
# TODO Some of that stuff is not really relavant any more
};
in
{
frogeye.hooks.lock = ''
${pkgs.coreutils}/bin/rm -rf "/tmp/cached_pass_$UID"
'';
programs = {
home-manager.enable = true;
bat = {
enable = true;
config = {
theme = "base16";
style = "full";
nixpkgs.config.allowUnfree = true;
programs =
let
commonRc = lib.strings.concatLines ([
''
# Colored ls
# TODO Doesn't allow completion. Check out lsd instead
_colored_ls() {
${pkgs.coreutils}/bin/ls -lh --color=always $@ | ${pkgs.gawk}/bin/awk '
BEGIN {
FPAT = "([[:space:]]*[^[:space:]]+)";
OFS = "";
}
{
$1 = "\033[36m" $1 "\033[0m";
$2 = "\033[31m" $2 "\033[0m";
$3 = "\033[32m" $3 "\033[0m";
$4 = "\033[32m" $4 "\033[0m";
$5 = "\033[31m" $5 "\033[0m";
$6 = "\033[34m" $6 "\033[0m";
$7 = "\033[34m" $7 "\033[0m";
print
}
'
}
alias ll="_colored_ls"
alias la="_colored_ls -a"
''
] ++ map (d: "mkdir -p ${d}") (builtins.attrValues direnv));
# TODO Those directory creations should probably done on home-manager activation
commonSessionVariables = {
TIME_STYLE = "+%Y-%m-%d %H:%M:%S";
# Less colors
LESS = "-R";
LESS_TERMCAP_mb = "$(echo $'\\E[1;31m')"; # begin blink
LESS_TERMCAP_md = "$(echo $'\\E[1;36m')"; # begin bold
LESS_TERMCAP_me = "$(echo $'\\E[0m')"; # reset bold/blink
LESS_TERMCAP_so = "$(echo $'\\E[01;44;33m')"; # begin reverse video
LESS_TERMCAP_se = "$(echo $'\\E[0m')"; # reset reverse video
LESS_TERMCAP_us = "$(echo $'\\E[1;32m')"; # begin underline
LESS_TERMCAP_ue = "$(echo $'\\E[0m')"; # reset underline
# Fzf
FZF_COMPLETION_OPTS = "${lib.strings.concatStringsSep " " config.programs.fzf.fileWidgetOptions}";
};
treatsHomeAsJunk = [
# Programs that think $HOME is a reasonable place to put their junk
# and don't allow the user to change those questionable choices
"adb"
"audacity"
"binwalk" # Should use .config according to the GitHub code though
"cabal" # TODO May have options but last time I tried it it crashed
"cmake"
"ddd"
"ghidra"
"itch"
"simplescreenrecorder" # Easy fix https://github.com/MaartenBaert/ssr/blob/1556ae456e833992fb6d39d40f7c7d7c337a4160/src/Main.cpp#L252
"vd"
"wpa_cli"
# TODO Maybe we can do something about node-gyp
];
commonShellAliases = {
# Completion for existing commands
ls = "ls -h --color=auto";
mkdir = "mkdir -v";
# cp = "cp -i"; # Disabled because conflicts with the ZSH/Bash one. This separation is confusing I swear.
mv = "mv -iv";
free = "free -h";
df = "df -h";
ffmpeg = "ffmpeg -hide_banner";
ffprobe = "ffprobe -hide_banner";
ffplay = "ffplay -hide_banner";
# TODO Add ipython --no-confirm-exit --pdb
# Frequent mistakes
sl = "ls";
al = "la";
mdkir = "mkdir";
systemclt = "systemctl";
please = "sudo";
# Shortcuts for commonly used commands
# ll = "ls -l"; # Disabled because would overwrite the colored one
# la = "ls -la"; # Eh maybe it's not that bad, but for now let's keep compatibility
s = "sudo -s -E";
# Give additional config to those programs, and not have them in my path
bower = "bower --config.storage.packages=${config.xdg.cacheHome}/bower/packages --config.storage.registry=${config.xdg.cacheHome}/bower/registry --config.storage.links=${config.xdg.cacheHome}/bower/links";
gdb = "gdb -x ${config.xdg.configHome}/gdbinit";
iftop = "iftop -c ${config.xdg.configHome}/iftoprc";
lmms = "lmms --config ${config.xdg.configHome}/lmmsrc.xml";
# Preference
vi = "nvim";
vim = "nvim";
wol = "wakeonlan"; # TODO Really, isn't wol better? Also wtf Arch aliases to pass because neither is installed anyways x)
mutt = "neomutt";
# Bash/Zsh only
cp = "cp -i --reflink=auto";
grep = "grep --color=auto";
dd = "dd status=progress";
rm = "rm -v --one-file-system";
# free = "free -m"; # Disabled because... no? Why?
diff = "diff --color=auto";
dmesg = "dmesg --ctime";
wget = "wget --hsts-file ${config.xdg.cacheHome}/wget-hsts";
# Imported from scripts
rms = ''${pkgs.findutils}/bin/find . -name "*.sync-conflict-*" -delete''; # Remove syncthing conflict files
pw = ''${pkgs.pwgen}/bin/pwgen 32 -y''; # Generate passwords. ln((26*2+10)**32)/ln(2) ≅ 190 bits of entropy
newestFile = ''${pkgs.findutils}/bin/find -type f -printf '%T+ %p\n' | sort | tail'';
oldestFile = ''${pkgs.findutils}/bin/find -type f -printf '%T+ %p\n' | sort | head'';
tracefiles = ''${pkgs.strace}/bin/strace -f -t -e trace=file'';
} // lib.attrsets.mergeAttrsList (map (p: { "${p}" = "HOME=${config.xdg.cacheHome}/junkhome ${p}"; }) treatsHomeAsJunk);
# TODO Maybe make nixpkg wrapper instead? So it also works from dmenu
# Could also accept my fate... Home-manager doesn't necessarily make it easy to put things out of the home directory
historySize = 100000;
historyFile = "${config.xdg.stateHome}/shell_history";
in
{
home-manager.enable = true;
bash = {
enable = true;
bashrcExtra = lib.strings.concatLines [
commonRc
''
shopt -s expand_aliases
shopt -s histappend
''
];
sessionVariables = commonSessionVariables;
historySize = historySize;
historyFile = historyFile;
historyFileSize = historySize;
historyControl = [ "erasedups" "ignoredups" "ignorespace" ];
shellAliases = commonShellAliases // config.frogeye.shellAliases;
};
zsh = {
enable = true;
enableAutosuggestions = true;
enableCompletion = true;
syntaxHighlighting.enable = true;
historySubstringSearch.enable = true;
initExtra = lib.strings.concatLines [
commonRc
(builtins.readFile ./zshrc.sh)
];
defaultKeymap = "viins";
history = {
size = historySize;
save = historySize;
path = historyFile;
expireDuplicatesFirst = true;
};
sessionVariables = commonSessionVariables;
shellAliases = commonShellAliases // config.frogeye.shellAliases;
};
dircolors = {
enable = true;
enableBashIntegration = true;
enableZshIntegration = true;
# UPST This thing put stuff in .dircolors when it actually doesn't have to
};
powerline-go = {
enable = true;
modules = [ "user" "host" "venv" "cwd" "perms" "git" ];
modulesRight = [ "jobs" "exit" "duration" "load" ];
settings = {
colorize-hostname = true;
max-width = 25;
cwd-max-dir-size = 10;
duration = "$( test -n \"$__TIMER\" && echo $(( $EPOCHREALTIME - $\{__TIMER:-EPOCHREALTIME})) || echo 0 )";
# UPST Implement this properly in home-manager, would allow for bash support
};
extraUpdatePS1 = ''
unset __TIMER
echo -en "\033]0; $USER@$HOST $PWD\007"
'';
};
gpg = {
enable = true;
homedir = "${config.xdg.stateHome}/gnupg";
settings = {
# Remove fluff
no-greeting = true;
no-emit-version = true;
no-comments = true;
# Output format that I prefer
keyid-format = "0xlong";
# Show fingerprints
with-fingerprint = true;
# Make sure to show if key is invalid
# (should be default on most platform,
# but just to be sure)
list-options = "show-uid-validity";
verify-options = "show-uid-validity";
# Stronger algorithm (https://wiki.archlinux.org/title/GnuPG#Different_algorithm)
personal-digest-preferences = "SHA512";
cert-digest-algo = "SHA512";
default-preference-list = "SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed";
personal-cipher-preferences = "TWOFISH CAMELLIA256 AES 3DES";
};
publicKeys = [{
source = builtins.fetchurl {
url = "https://keys.openpgp.org/vks/v1/by-fingerprint/4FBA930D314A03215E2CDB0A8312C8CAC1BAC289";
sha256 = "sha256:10y9xqcy1vyk2p8baay14p3vwdnlwynk0fvfbika65hz2z8yw2cm";
};
trust = "ultimate";
}];
};
fzf = {
enable = true;
enableZshIntegration = true;
defaultOptions = [ "--height 40%" "--layout=default" ];
fileWidgetOptions = [ "--preview '[[ -d {} ]] && ${pkgs.coreutils}/bin/ls -l --color=always {} || [[ \$(${pkgs.file}/bin/file --mime {}) =~ binary ]] && ${pkgs.file}/bin/file --brief {} || (${pkgs.highlight}/bin/highlight -O ansi -l {} || coderay {} || rougify {} || ${pkgs.coreutils}/bin/cat {}) 2> /dev/null | head -500'" ];
# file and friends are not in PATH by default... so here we want aboslute paths, which means those won't get reloaded. Meh.
};
# TODO highlight or bat
nix-index = {
enable = false; # TODO Index is impossible to generate, should use https://github.com/nix-community/nix-index-database
# but got no luck without flakes
enableZshIntegration = true;
};
less.enable = true;
git = {
enable = true;
package = pkgs.gitFull;
aliases = {
"git" = "!exec git"; # In case I write one too many git
};
ignores = [
"*.swp"
"*.swo"
"*.ycm_extra_conf.py"
"tags"
".mypy_cache"
];
lfs.enable = true;
userEmail = lib.mkDefault "geoffrey@frogeye.fr";
userName = lib.mkDefault "Geoffrey Frogeye";
extraConfig = {
core = {
editor = "nvim";
};
push = {
default = "matching";
};
pull = {
ff = "only";
};
} // lib.optionalAttrs config.frogeye.desktop.xorg {
diff.tool = "meld";
difftool.prompt = false;
"difftool \"meld\"".cmd = "${pkgs.meld}/bin/meld \"$LOCAL\" \"$REMOTE\"";
# This escapes quotes, which isn't the case in the original, hoping this isn't an issue.
};
# TODO Delta syntax highlighter... and other cool-looking options?
};
readline = {
enable = true;
variables = {
"bell-style" = "none";
"colored-completion-prefix" = true;
"colored-stats" = true;
"completion-ignore-case" = true;
"completion-query-items" = 200;
"editing-mode" = "vi";
"history-preserve-point" = true;
"history-size" = 10000;
"horizontal-scroll-mode" = false;
"mark-directories" = true;
"mark-modified-lines" = false;
"mark-symlinked-directories" = true;
"match-hidden-files" = true;
"menu-complete-display-prefix" = true;
"page-completions" = true;
"print-completions-horizontally" = false;
"revert-all-at-newline" = false;
"show-all-if-ambiguous" = true;
"show-all-if-unmodified" = true;
"show-mode-in-prompt" = true;
"skip-completed-text" = true;
"visible-stats" = false;
};
extraConfig = builtins.readFile ./inputrc;
};
tmux =
let
themepack = pkgs.tmuxPlugins.mkTmuxPlugin
rec {
pluginName = "tmux-themepack";
version = "1.1.0";
rtpFilePath = "themepack.tmux";
src = pkgs.fetchFromGitHub {
owner = "jimeh";
repo = "tmux-themepack";
rev = "${version}";
sha256 = "f6y92kYsKDFanNx5ATx4BkaB/E7UrmyIHU/5Z01otQE=";
};
};
in
{
enable = true;
mouse = false;
clock24 = true;
# TODO Vim mode?
plugins = with pkgs.tmuxPlugins; [
sensible
];
extraConfig = builtins.readFile ./tmux.conf + "source-file ${themepack}/share/tmux-plugins/tmux-themepack/powerline/default/green.tmuxtheme\n";
};
translate-shell.enable = true; # TODO Cool config?
password-store.enable = true;
};
bash.shellAliases = {
# Replacement commands
# ls = "lsd"; # lsd is suuuper slow for large directories
cat = "bat -pp";
# Completion for existing commands
mkdir = "mkdir -v";
# cp = "cp -i"; # Disabled because conflicts with the ZSH/Bash one. This separation is confusing I swear.
mv = "mv -iv";
free = "free -h";
df = "df -h";
ffmpeg = "ffmpeg -hide_banner";
ffprobe = "ffprobe -hide_banner";
ffplay = "ffplay -hide_banner";
numbat = "numbat --intro-banner off";
insect = "numbat";
# Frequent mistakes
sl = "ls";
al = "la";
mdkir = "mkdir";
systemclt = "systemctl";
please = "sudo";
# Shortcuts for commonly used commands
ll = "lsd -l";
la = "lsd -la";
s = "sudo -s -E";
# Preference
wol = "wakeonlan"; # TODO Really, isn't wol better? Also wtf Arch aliases to pass because neither is installed anyways x)
mutt = "neomutt";
# Bash/Zsh only
cp = "cp -i --reflink=auto";
grep = "grep --color=auto";
dd = "dd status=progress";
rm = "rm -v --one-file-system";
# free = "free -m"; # Disabled because... no? Why?
diff = "diff --color=auto";
dmesg = "dmesg --ctime";
wget = "wget --hsts-file ${config.xdg.cacheHome}/wget-hsts";
# Imported from scripts
rms = ''${pkgs.findutils}/bin/find . -name "*.sync-conflict-*" -delete''; # Remove syncthing conflict files
newestFile = ''${pkgs.findutils}/bin/find -type f -printf '%T+ %p\n' | sort | tail'';
oldestFile = ''${pkgs.findutils}/bin/find -type f -printf '%T+ %p\n' | sort | head'';
};
thefuck = {
enable = true;
services = {
gpg-agent = {
enable = true; # TODO Consider not enabling it when not having any private key
enableBashIntegration = true;
enableZshIntegration = true;
pinentryFlavor = "gtk2"; # Falls back to curses when needed
};
lsd = {
enable = true;
settings = {
size = "short";
};
colors = {
# Base16 only, so it reuses the current theme.
date = { day-old = 4; hour-old = 6; older = 5; };
git-status = { conflicted = 14; default = 13; deleted = 1; ignored = 13; modified = 3; new-in-index = 2; new-in-workdir = 2; renamed = 4; typechange = 3; unmodified = 13; };
group = 6;
inode = { invalid = 245; valid = 13; };
links = { invalid = 9; valid = 14; };
permission = { acl = 6; context = 14; exec = 1; exec-sticky = 5; no-access = 245; octal = 6; read = 2; write = 3; };
size = { large = 1; medium = 9; none = 11; small = 3; };
tree-edge = 13;
user = 2;
# TODO Syncs a bit too often, also constantly asks for passphrase, which is annoying.
git-sync = {
enable = false;
repositories = {
dotfiles = {
path = "${config.xdg.configHome}/dotfiles";
uri = lib.mkDefault "https://git.frogeye.fr/geoffrey/dotfiles.git";
};
};
};
dircolors = {
enable = true;
enableBashIntegration = true;
enableZshIntegration = true;
# UPST This thing put stuff in .dircolors when it actually doesn't have to
};
git.enable = true;
gpg.enable = true;
fzf = {
enable = true;
enableZshIntegration = true;
defaultOptions = [ "--height 40%" "--layout=default" ];
fileWidgetOptions = [ "--preview '[[ -d {} ]] && ${pkgs.coreutils}/bin/ls -l --color=always {} || [[ \$(${pkgs.file}/bin/file --mime {}) =~ binary ]] && ${pkgs.file}/bin/file --brief {} || (${pkgs.highlight}/bin/highlight -O ansi -l {} || coderay {} || rougify {} || ${pkgs.coreutils}/bin/cat {}) 2> /dev/null | head -500'" ];
# TODO Above not working... not really used either?
# file and friends are not in PATH by default... so here we want aboslute paths, which means those won't get reloaded. Meh.
};
less.enable = true;
nixvim.enable = true;
readline = {
enable = true;
variables = {
"bell-style" = "none";
"colored-completion-prefix" = true;
"colored-stats" = true;
"completion-ignore-case" = true;
"completion-query-items" = 200;
"editing-mode" = "vi";
"history-preserve-point" = true;
"history-size" = 10000;
"horizontal-scroll-mode" = false;
"mark-directories" = true;
"mark-modified-lines" = false;
"mark-symlinked-directories" = true;
"match-hidden-files" = true;
"menu-complete-display-prefix" = true;
"page-completions" = true;
"print-completions-horizontally" = false;
"revert-all-at-newline" = false;
"show-all-if-ambiguous" = true;
"show-all-if-unmodified" = true;
"show-mode-in-prompt" = true;
"skip-completed-text" = true;
"visible-stats" = false;
};
xdg = {
configFile = {
"ccache.conf" = {
text = "ccache_dir = ${config.xdg.cacheHome}/ccache";
};
"gdbinit" = {
text = ''
define hook-quit
set confirm off
end
'';
};
"iftoprc" = {
text = ''
port-resolution: no
promiscuous: no
port-display: on
link-local: yes
use-bytes: yes
show-totals: yes
log-scale: yes
'';
};
"pythonstartup.py" = {
text = (builtins.readFile ./pythonstartup.py);
};
"screenrc" = {
text = (builtins.readFile ./screenrc);
};
extraConfig = builtins.readFile ./inputrc;
};
tmux.enable = true;
translate-shell.enable = true; # TODO Cool config?
};
home = {
activation = {
@ -144,82 +396,136 @@
'';
};
stateVersion = "23.11";
language = {
base = "en_US.UTF-8";
# time = "en_DK.UTF-8"; # TODO Disabled because complaints during nixos-rebuild switch
};
packages = with pkgs; [
# Terminal utils
# dotfiles dependencies
coreutils
moreutils
rename
which
file
# Pipe utils
bash
gnugrep
gnused
gawk
# Extraction
gnutar
openssl
wget
curl
python3Packages.pip
rename
which
# shell
zsh-completions
nix-zsh-completions
zsh-history-substring-search
powerline-go
neofetch
# nix utils
nix-diff
nix-tree
nix-output-monitor
# terminal essentials
file
moreutils
man
unzip
unrar
p7zip
# Documentation
man
tldr
neofetch
# remote
wget
curl
openssl
openssh
rsync
borgbackup
sshfs
# cleanup
ncdu
jdupes
duperemove
compsize
btdu
# toolbox
# local monitoring
htop
iotop
iftop
lsof
strace
pv
progress
speedtest-cli
# multimedia toolbox
sox
imagemagick
numbat
# hardware
pciutils
usbutils
dmidecode
lshw
# Locker
# password
pwgen
(pkgs.writeShellApplication {
name = "lock";
text = ''
${config.frogeye.hooks.lock}
${pkgs.vlock}/bin/vlock --all
'';
name = "git-sync-init";
# runtimeInputs = with pkgs; [ coreutils libnotify ];
text = (lib.strings.concatLines
(map (r: ''[ -d "${r.path}" ] || ${pkgs.git}/bin/git clone "${r.uri}" "${r.path}"'')
(lib.attrsets.attrValues config.services.git-sync.repositories)
)
);
})
# Mail
isync
msmtp
notmuch
neomutt
lynx
# Organisation
vdirsyncer
khard
khal
todoman
# TODO Lots of redundancy with other way things are defined here
] ++ lib.optionals pkgs.stdenv.isx86_64 [
nodePackages.insect
# TODO Use whatever replaces insect, hopefully that works on aarch64
];
sessionVariables = {
# Favourite commands
PAGER = "less";
EDITOR = "nvim";
# Extra config
BOOT9_PATH = "${config.xdg.dataHome}/citra-emu/sysdata/boot9.bin";
CCACHE_CONFIGPATH = "${config.xdg.configHome}/ccache.conf";
# INPUTRC = "${config.xdg.configHome}/inputrc"; # UPST Will use programs.readline, but doesn't allow path setting
LESSHISTFILE = "${config.xdg.stateHome}/lesshst";
NODE_REPL_HISTORY = "${config.xdg.cacheHome}/node_repl_history";
PYTHONSTARTUP = "${config.xdg.configHome}/pythonstartup.py";
# TODO I think we're not using the urxvt daemon on purpose?
# TODO this should be desktop only, as a few things are too.
SCREENRC = "${config.xdg.configHome}/screenrc";
SQLITE_HISTFILE = "${config.xdg.stateHome}/sqlite_history";
YARN_DISABLE_SELF_UPDATE_CHECK = "true"; # This also disable the creation of a ~/.yarnrc file
} // lib.optionalAttrs config.frogeye.desktop.xorg {
# Favourite commands
VISUAL = "nvim";
BROWSER = "${config.programs.qutebrowser.package}/bin/qutebrowser";
# Bash/ZSH only?
TIME_STYLE = "+%Y-%m-%d %H:%M:%S";
# Fzf
FZF_COMPLETION_OPTS = "${lib.strings.concatStringsSep " " config.programs.fzf.fileWidgetOptions}";
};
# Extra config
RXVT_SOCKET = "${config.xdg.stateHome}/urxvtd"; # Used to want -$HOME suffix, hopefullt this isn't needed
# XAUTHORITY = "${config.xdg.configHome}/Xauthority"; # Disabled as this causes lock-ups with DMs
} // direnv;
# TODO Session variables only get reloaded on login I think.
sessionPath = [
"${config.home.homeDirectory}/.local/bin"
"${config.home.homeDirectory}/.config/dotfiles/hm/scripts" # Not Nix path otherwise it gets converted into store,
# and then every time you want to modify a script you have to rebuild and re-login...
"${config.home.sessionVariables.GOPATH}"
(builtins.toString ./scripts)
];
file = {
".face" = { # TODO Doesn't show on NixOS. See https://wiki.archlinux.org/title/LightDM#Changing_your_avatar ?
source = pkgs.runCommand "face.png" { } "${pkgs.inkscape}/bin/inkscape ${./face.svg} -w 1024 -o $out";
};
};
# FIXME .config/home-manager/home.nix link. Using hostname?
};
}

View file

@ -1,29 +1,15 @@
{ stylix, ... }:
{ ... }:
{
imports = [
../common/frogarized
../options.nix
./accounts
./brightness
./common.nix
./desktop
./dev
./desktop.nix
./dev.nix
./extra.nix
./gaming
./git
./gpg
./homealone.nix
./monitoring
./nix
./pager
./password
./prompt
./rebuild
./shell
./ssh.nix
stylix.homeManagerModules.stylix
./theme
./tmux
./vim
./style.nix
./usernix
./vim.nix
];
}

706
hm/desktop.nix Normal file
View file

@ -0,0 +1,706 @@
{ pkgs, config, lib, ... }:
let
nixgl = import
(builtins.fetchGit {
url = "https://github.com/nix-community/nixGL";
rev = "489d6b095ab9d289fe11af0219a9ff00fe87c7c5";
})
{ };
nixGLIntelPrefix = "${nixgl.nixVulkanIntel}/bin/nixVulkanIntel ${nixgl.nixGLIntel}/bin/nixGLIntel ";
wmPrefix = "${lib.optionalString config.frogeye.desktop.nixGLIntel nixGLIntelPrefix}";
in
{
imports = [
./frobar
];
config = lib.mkIf config.frogeye.desktop.xorg {
frogeye.shellAliases = {
noise = ''${pkgs.sox}/bin/play -c 2 -n synth $'' + ''{1}noise'';
beep = ''${pkgs.sox}/bin/play -n synth sine E5 sine A4 remix 1-2 fade 0.5 1.2 0.5 2> /dev/null'';
# n = "$HOME/.config/i3/terminal & disown"; # Not used anymore since alacritty daemon mode doesn't preserve environment variables
x = "startx ${config.home.homeDirectory}/${config.xsession.scriptPath}; logout";
# TODO Is it possible to not start nvidia stuff on nixOS?
# nx = "nvidia-xrun ${config.xsession.scriptPath}; sudo systemctl start nvidia-xrun-pm; logout";
};
xsession = {
enable = true;
# Not using config.xdg.configHome because it needs to be $HOME-relative paths and path manipulation is hard
scriptPath = ".config/xsession";
profilePath = ".config/xprofile";
windowManager = {
command = lib.mkForce "${wmPrefix} ${config.xsession.windowManager.i3.package}/bin/i3";
i3 = {
enable = true;
config =
let
# lockColors = with config.lib.stylix.colors.withHashtag; { a = base00; b = base01; d = base00; }; # Black or White, depending on current theme
# lockColors = with config.lib.stylix.colors.withHashtag; { a = base0A; b = base0B; d = base00; }; # Green + Yellow
lockColors = { a = "#82a401"; b = "#466c01"; d = "#648901"; }; # Old
lockSvg = pkgs.writeText "lock.svg" "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 50 50\" height=\"50\" width=\"50\"><path fill=\"${lockColors.a}\" d=\"M0 50h50V0H0z\"/><path d=\"M0 0l50 50H25L0 25zm50 0v25L25 0z\" fill=\"${lockColors.b}\"/></svg>";
lockPng = pkgs.runCommand "lock.png" { } "${pkgs.imagemagick}/bin/convert ${lockSvg} $out";
locker = pkgs.writeShellScript "i3-locker"
''
# Remove SSH and GPG keys from keystores
${pkgs.openssh}/bin/ssh-add -D
echo RELOADAGENT | ${pkgs.gnupg}/bin/gpg-connect-agent
${pkgs.coreutils}/bin/rm -rf "/tmp/cached_pass_$UID"
${pkgs.lightdm}/bin/dm-tool lock
# TODO Does that work for all DMs?
# TODO Might want to use i3lock on NixOS configs still?
if [ $? -ne 0 ]; then
if [ -d ${config.xdg.cacheHome}/lockpatterns ]
then
pattern=$(${pkgs.findutils} ${config.xdg.cacheHome}/lockpatterns | sort -R | head -1)
else
pattern=${lockPng}
fi
revert() {
${pkgs.xorg.xset}/bin/xset dpms 0 0 0
}
trap revert SIGHUP SIGINT SIGTERM
${pkgs.xorg.xset}/bin/xset dpms 5 5 5
${pkgs.i3lock}/bin/i3lock --nofork --color ${builtins.substring 1 6 lockColors.d} --image=$pattern --tiling --ignore-empty-password
revert
fi
'';
focus = "exec ${ pkgs.writeShellScript "i3-focus-window"
''
WINDOW=`${pkgs.xdotool}/bin/xdotool getwindowfocus`
eval `${pkgs.xdotool}/bin/xdotool getwindowgeometry --shell $WINDOW` # this brings in variables WIDTH and HEIGHT
TX=`${pkgs.coreutils}/bin/expr $WIDTH / 2`
TY=`${pkgs.coreutils}/bin/expr $HEIGHT / 2`
${pkgs.xdotool}/bin/xdotool mousemove -window $WINDOW $TX $TY
''
}";
mode_system = "[L] Vérouillage [E] Déconnexion [S] Veille [H] Hibernation [R] Redémarrage [P] Extinction";
mode_resize = "Resize";
mode_pres_main = "Presentation (main display)";
mode_pres_sec = "Presentation (secondary display)";
mode_screen = "Screen setup [A] Auto [L] Load [S] Save [R] Remove [D] Default";
mode_temp = "Temperature [R] Red [D] Dust storm [C] Campfire [O] Normal [A] All nighter [B] Blue";
fonts = config.stylix.fonts;
in
{
modifier = "Mod4";
fonts = {
names = [ fonts.sansSerif.name ];
};
terminal = "alacritty";
colors = let ignore = "#ff00ff"; in
with config.lib.stylix.colors.withHashtag; lib.mkForce {
focused = { border = base0B; background = base0B; text = base00; indicator = base00; childBorder = base0B; };
focusedInactive = { border = base02; background = base02; text = base05; indicator = base02; childBorder = base02; };
unfocused = { border = base05; background = base04; text = base00; indicator = base04; childBorder = base00; };
urgent = { border = base0F; background = base08; text = base00; indicator = base08; childBorder = base0F; };
placeholder = { border = ignore; background = base00; text = base05; indicator = ignore; childBorder = base00; };
background = base07;
# I set the color of the active tab as the the background color of the terminal so they merge together.
};
focus.followMouse = false;
keybindings =
let
mod = config.xsession.windowManager.i3.config.modifier;
rofi = "exec --no-startup-id ${config.programs.rofi.package}/bin/rofi";
pactl = "exec ${pkgs.pulseaudio}/bin/pactl"; # TODO Use NixOS package if using NixOS
screenshots_dir = config.xdg.userDirs.extraConfig.XDG_SCREENSHOTS_DIR;
scrot = "${pkgs.scrot}/bin/scrot --exec '${pkgs.coreutils}/bin/mv $f ${screenshots_dir}/ && ${pkgs.optipng}/bin/optipng ${screenshots_dir}/$f'";
in
{
# Compatibility layer for people coming from other backgrounds
"Mod1+Tab" = "${rofi} -modi window -show window";
"Mod1+F2" = "${rofi} -modi drun -show drun";
"Mod1+F4" = "kill";
# kill focused window
"${mod}+z" = "kill";
button2 = "kill";
# Rofi
"${mod}+c" = "exec --no-startup-id ${config.programs.rofi.pass.package}/bin/rofi-pass --last-used";
# TODO Try autopass.cr
# 23.11 config.programs.rofi.pass.package
"${mod}+i" = "exec --no-startup-id ${pkgs.rofimoji}/bin/rofimoji";
"${mod}+plus" = "${rofi} -modi ssh -show ssh";
"${mod}+ù" = "${rofi} -modi ssh -show ssh -ssh-command '{terminal} -e {ssh-client} {host} -t \"sudo -s -E\"'";
# TODO In which keyboard layout?
"${mod}+Tab" = "${rofi} -modi window -show window";
# start program launcher
"${mod}+d" = "${rofi} -modi run -show run";
"${mod}+Shift+d" = "${rofi} -modi drun -show drun";
# Start Applications
"${mod}+Return" = "exec ${
pkgs.writeShellScript "terminal" "${config.programs.alacritty.package}/bin/alacritty msg create-window || exec ${config.programs.alacritty.package}/bin/alacritty -e zsh"
# -e zsh is for systems where I can't configure my user's shell
# TODO Is a shell script even required?
}";
"${mod}+Shift+Return" = "exec ${config.programs.urxvt.package}/bin/urxvt";
"${mod}+p" = "exec ${pkgs.xfce.thunar}/bin/thunar";
"${mod}+m" = "exec ${config.programs.qutebrowser.package}/bin/qutebrowser --override-restore --backend=webengine";
# TODO --backend not useful anymore
# Volume control
"XF86AudioRaiseVolume" = "${pactl} set-sink-mute @DEFAULT_SINK@ false; ${pactl} set-sink-volume @DEFAULT_SINK@ +5%";
"XF86AudioLowerVolume" = "${pactl} set-sink-mute @DEFAULT_SINK@ false; ${pactl} set-sink-volume @DEFAULT_SINK@ -5%";
"XF86AudioMute" = "${pactl} set-sink-mute @DEFAULT_SINK@ true";
"${mod}+F7" = "${pactl} suspend-sink @DEFAULT_SINK@ 1; ${pactl} suspend-sink @DEFAULT_SINK@ 0"; # Re-synchronize bluetooth headset
"${mod}+F11" = "exec ${pkgs.pavucontrol}/bin/pavucontrol";
"${mod}+F12" = "exec ${pkgs.pavucontrol}/bin/pavucontrol";
# TODO Find pacmixer?
# Media control
"XF86AudioPrev" = "exec ${pkgs.mpc-cli}/bin/mpc prev";
"XF86AudioPlay" = "exec ${pkgs.mpc-cli}/bin/mpc toggle";
"XF86AudioNext" = "exec ${pkgs.mpc-cli}/bin/mpc next";
# Backlight
"XF86MonBrightnessUp" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set +5%";
"XF86MonBrightnessDown" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set 5%-";
# Misc
"${mod}+F10" = "exec ${ pkgs.writeShellScript "show-keyboard-layout"
''
layout=`${pkgs.xorg.setxkbmap}/bin/setxkbmap -query | ${pkgs.gnugrep}/bin/grep ^layout: | ${pkgs.gawk}/bin/awk '{ print $2 }'`
${pkgs.libgnomekbd}/bin/gkbd-keyboard-display -l $layout
''
}";
# Screenshots
"Print" = "exec ${scrot} --focused";
"${mod}+Print" = "exec ${scrot}";
"Ctrl+Print" = "exec ${pkgs.coreutils}/bin/sleep 1 && ${scrot} --select";
# TODO Try using bindsym --release instead of sleep
# change focus
"${mod}+h" = "focus left; ${focus}";
"${mod}+j" = "focus down; ${focus}";
"${mod}+k" = "focus up; ${focus}";
"${mod}+l" = "focus right; ${focus}";
# move focused window
"${mod}+Shift+h" = "move left; ${focus}";
"${mod}+Shift+j" = "move down; ${focus}";
"${mod}+Shift+k" = "move up; ${focus}";
"${mod}+Shift+l" = "move right; ${focus}";
# workspace back and forth (with/without active container)
"${mod}+b" = "workspace back_and_forth; ${focus}";
"${mod}+Shift+b" = "move container to workspace back_and_forth; workspace back_and_forth; ${focus}";
# Change container layout
"${mod}+g" = "split h; ${focus}";
"${mod}+v" = "split v; ${focus}";
"${mod}+f" = "fullscreen toggle; ${focus}";
"${mod}+s" = "layout stacking; ${focus}";
"${mod}+w" = "layout tabbed; ${focus}";
"${mod}+e" = "layout toggle split; ${focus}";
"${mod}+Shift+space" = "floating toggle; ${focus}";
# Focus container
"${mod}+space" = "focus mode_toggle; ${focus}";
"${mod}+a" = "focus parent; ${focus}";
"${mod}+q" = "focus child; ${focus}";
# Switch to workspace
"${mod}+1" = "workspace 1; ${focus}";
"${mod}+2" = "workspace 2; ${focus}";
"${mod}+3" = "workspace 3; ${focus}";
"${mod}+4" = "workspace 4; ${focus}";
"${mod}+5" = "workspace 5; ${focus}";
"${mod}+6" = "workspace 6; ${focus}";
"${mod}+7" = "workspace 7; ${focus}";
"${mod}+8" = "workspace 8; ${focus}";
"${mod}+9" = "workspace 9; ${focus}";
"${mod}+0" = "workspace 10; ${focus}";
# TODO Prevent repetitions, see workspace assignation for example
#navigate workspaces next / previous
"${mod}+Ctrl+h" = "workspace prev_on_output; ${focus}";
"${mod}+Ctrl+l" = "workspace next_on_output; ${focus}";
"${mod}+Ctrl+j" = "workspace prev; ${focus}";
"${mod}+Ctrl+k" = "workspace next; ${focus}";
# Move to workspace next / previous with focused container
"${mod}+Ctrl+Shift+h" = "move container to workspace prev_on_output; workspace prev_on_output; ${focus}";
"${mod}+Ctrl+Shift+l" = "move container to workspace next_on_output; workspace next_on_output; ${focus}";
"${mod}+Ctrl+Shift+j" = "move container to workspace prev; workspace prev; ${focus}";
"${mod}+Ctrl+Shift+k" = "move container to workspace next; workspace next; ${focus}";
# move focused container to workspace
"${mod}+ctrl+1" = "move container to workspace 1; ${focus}";
"${mod}+ctrl+2" = "move container to workspace 2; ${focus}";
"${mod}+ctrl+3" = "move container to workspace 3; ${focus}";
"${mod}+ctrl+4" = "move container to workspace 4; ${focus}";
"${mod}+ctrl+5" = "move container to workspace 5; ${focus}";
"${mod}+ctrl+6" = "move container to workspace 6; ${focus}";
"${mod}+ctrl+7" = "move container to workspace 7; ${focus}";
"${mod}+ctrl+8" = "move container to workspace 8; ${focus}";
"${mod}+ctrl+9" = "move container to workspace 9; ${focus}";
"${mod}+ctrl+0" = "move container to workspace 10; ${focus}";
# move to workspace with focused container
"${mod}+shift+1" = "move container to workspace 1; workspace 1; ${focus}";
"${mod}+shift+2" = "move container to workspace 2; workspace 2; ${focus}";
"${mod}+shift+3" = "move container to workspace 3; workspace 3; ${focus}";
"${mod}+shift+4" = "move container to workspace 4; workspace 4; ${focus}";
"${mod}+shift+5" = "move container to workspace 5; workspace 5; ${focus}";
"${mod}+shift+6" = "move container to workspace 6; workspace 6; ${focus}";
"${mod}+shift+7" = "move container to workspace 7; workspace 7; ${focus}";
"${mod}+shift+8" = "move container to workspace 8; workspace 8; ${focus}";
"${mod}+shift+9" = "move container to workspace 9; workspace 9; ${focus}";
"${mod}+shift+0" = "move container to workspace 10; workspace 10; ${focus}";
# move workspaces to screen (arrow keys)
"${mod}+ctrl+shift+Right" = "move workspace to output right; ${focus}";
"${mod}+ctrl+shift+Left" = "move workspace to output left; ${focus}";
"${mod}+Ctrl+Shift+Up" = "move workspace to output above; ${focus}";
"${mod}+Ctrl+Shift+Down" = "move workspace to output below; ${focus}";
# i3 control
"${mod}+Shift+c" = "reload";
"${mod}+Shift+r" = "restart";
"${mod}+Shift+e" = "exit";
# Screen off commands
"${mod}+F1" = "exec --no-startup-id ${pkgs.bash}/bin/sh -c \"${pkgs.coreutils}/bin/sleep .25 && ${pkgs.xorg.xset}/bin/xset dpms force off\"";
# TODO --release?
"${mod}+F4" = "exec --no-startup-id ${pkgs.xautolock}/bin/xautolock -disable";
"${mod}+F5" = "exec --no-startup-id ${pkgs.xautolock}/bin/xautolock -enable";
# Modes
"${mod}+Escape" = "mode ${mode_system}";
"${mod}+r" = "mode ${mode_resize}";
"${mod}+Shift+p" = "mode ${mode_pres_main}";
"${mod}+t" = "mode ${mode_screen}";
"${mod}+y" = "mode ${mode_temp}";
};
modes = let return_bindings = {
"Return" = "mode default";
"Escape" = "mode default";
}; in
{
"${mode_system}" = {
"l" = "exec --no-startup-id exec ${locker}, mode default";
"e" = "exit, mode default";
"s" = "exec --no-startup-id exec ${locker} & ${pkgs.systemd}/bin/systemctl suspend --check-inhibitors=no, mode default";
"h" = "exec --no-startup-id exec ${locker} & ${pkgs.systemd}/bin/systemctl hibernate, mode default";
"r" = "exec --no-startup-id ${pkgs.systemd}/bin/systemctl reboot, mode default";
"p" = "exec --no-startup-id ${pkgs.systemd}/bin/systemctl poweroff -i, mode default";
} // return_bindings;
"${mode_resize}" = {
"h" = "resize shrink width 10 px or 10 ppt; ${focus}";
"j" = "resize grow height 10 px or 10 ppt; ${focus}";
"k" = "resize shrink height 10 px or 10 ppt; ${focus}";
"l" = "resize grow width 10 px or 10 ppt; ${focus}";
} // return_bindings;
"${mode_pres_main}" = {
"b" = "workspace 3, workspace 4, mode ${mode_pres_sec}";
"q" = "mode default";
"Return" = "mode default";
};
"${mode_pres_sec}" = {
"b" = "workspace 1, workspace 2, mode ${mode_pres_main}";
"q" = "mode default";
"Return" = "mode default";
};
"${mode_screen}" =
let
builtin_configs = [ "off" "common" "clone-largest" "horizontal" "vertical" "horizontal-reverse" "vertical-reverse" ];
autorandrmenu = { title, option, builtin ? false }: pkgs.writeShellScript "autorandrmenu"
''
shopt -s nullglob globstar
profiles="${if builtin then lib.strings.concatLines builtin_configs else ""}$(${pkgs.autorandr}/bin/autorandr | ${pkgs.gawk}/bin/awk '{ print $1 }')"
profile="$(echo "$profiles" | ${config.programs.rofi.package}/bin/rofi -dmenu -p "${title}")"
[[ -n "$profile" ]] || exit
${pkgs.autorandr}/bin/autorandr ${option} "$profile"
'';
in
{
"a" = "exec ${pkgs.autorandr}/bin/autorandr --change --force, mode default";
"l" = "exec ${autorandrmenu {title="Load profile"; option="--load"; builtin = true;}}, mode default";
"s" = "exec ${autorandrmenu {title="Save profile"; option="--save";}}, mode default";
"r" = "exec ${autorandrmenu {title="Remove profile"; option="--remove";}}, mode default";
"d" = "exec ${autorandrmenu {title="Default profile"; option="--default"; builtin = true;}}, mode default";
} // return_bindings;
"${mode_temp}" = {
"r" = "exec ${pkgs.sct}/bin/sct 1000";
"d" = "exec ${pkgs.sct}/bin/sct 2000";
"c" = "exec ${pkgs.sct}/bin/sct 4500";
"o" = "exec ${pkgs.sct}/bin/sct";
"a" = "exec ${pkgs.sct}/bin/sct 8000";
"b" = "exec ${pkgs.sct}/bin/sct 10000";
} // return_bindings;
};
window = {
hideEdgeBorders = "both";
titlebar = false; # So that single-container screens are basically almost fullscreen
commands = [
# Open specific applications in floating mode
{ criteria = { class = "Firefox"; }; command = "layout tabbed"; } # Doesn't seem to work anymore
{ criteria = { class = "qutebrowser"; }; command = "layout tabbed"; }
{ criteria = { title = "^pdfpc.*"; window_role = "presenter"; }; command = "move to output left, fullscreen"; }
{ criteria = { title = "^pdfpc.*"; window_role = "presentation"; }; command = "move to output right, fullscreen"; }
# switch to workspace with urgent window automatically
{ criteria = { urgent = "latest"; }; command = "focus"; }
];
};
floating = {
criteria = [
{ title = "pacmixer"; }
{ window_role = "pop-up"; }
{ window_role = "task_dialog"; }
];
};
startup = [
# Lock screen after 10 minutes
{ notification = false; command = "${pkgs.xautolock}/bin/xautolock -time 10 -locker '${pkgs.xorg.xset}/bin/xset dpms force standby' -killtime 1 -killer ${locker}"; }
{
notification = false;
command = "${pkgs.writeShellApplication {
name = "batteryNotify";
runtimeInputs = with pkgs; [coreutils libnotify];
text = builtins.readFile ./batteryNotify.sh;
# TODO Use batsignal instead?
# TODO Only on computers with battery
}}/bin/batteryNotify";
}
# TODO There's a services.screen-locker.xautolock but not sure it can match the above command
];
workspaceLayout = "tabbed";
focus.mouseWarping = true; # i3 only supports warping to workspace, hence ${focus}
workspaceOutputAssign =
let
x11_screens = config.frogeye.desktop.x11_screens;
workspaces = map (i: { name = toString i; key = toString (lib.mod i 10); }) (lib.lists.range 1 10);
forEachWorkspace = f: map (w: f { w = w; workspace = ((builtins.elemAt workspaces w)); }) (lib.lists.range 0 ((builtins.length workspaces) - 1));
in
forEachWorkspace ({ w, workspace }: { output = builtins.elemAt x11_screens (lib.mod w (builtins.length x11_screens)); workspace = workspace.name; });
};
};
};
numlock.enable = config.frogeye.desktop.numlock;
};
programs = {
# Browser
qutebrowser = {
enable = true;
keyBindings = {
normal = {
# Match tab behaviour to i3. Not that I use them.
"H" = "tab-prev";
"J" = "back";
"K" = "forward";
"L" = "tab-next";
# "T" = null;
"af" = "spawn --userscript freshrss"; # TODO Broken?
"as" = "spawn --userscript shaarli"; # TODO I don't use shaarli anymore
# "d" = null;
"u" = "undo --window";
# TODO Unbind d and T (?)
};
};
loadAutoconfig = true;
searchEngines = rec {
DEFAULT = ecosia;
alpinep = "https://pkgs.alpinelinux.org/packages?name={}&branch=edge";
ampwhat = "http://www.amp-what.com/unicode/search/{}";
arch = "https://wiki.archlinux.org/?search={}";
archp = "https://www.archlinux.org/packages/?q={}";
aur = "https://aur.archlinux.org/packages/?K={}";
aw = ampwhat;
ddg = duckduckgo;
dockerhub = "https://hub.docker.com/search/?isAutomated=0&isOfficial=0&page=1&pullCount=0&q={}&starCount=0";
duckduckgo = "https://duckduckgo.com/?q={}&ia=web";
ecosia = "https://www.ecosia.org/search?q={}";
gfr = "https://www.google.fr/search?hl=fr&q={}";
g = google;
gh = github;
gi = "http://images.google.com/search?q={}";
giphy = "https://giphy.com/search/{}";
github = "https://github.com/search?q={}";
google = "https://www.google.fr/search?q={}";
invidious = "https://invidious.frogeye.fr/search?q={}";
inv = invidious;
npm = "https://www.npmjs.com/search?q={}";
q = qwant;
qwant = "https://www.qwant.com/?t=web&q={}";
wolfram = "https://www.wolframalpha.com/input/?i={}";
youtube = "https://www.youtube.com/results?search_query={}";
yt = youtube;
};
settings = {
downloads.location.prompt = false;
tabs = {
show = "never";
tabs_are_windows = true;
};
url = rec {
open_base_url = true;
start_pages = lib.mkDefault "https://geoffrey.frogeye.fr/blank.html";
default_page = start_pages;
};
content = {
# I had this setting below, not sure if it did something special
# config.set("content.cookies.accept", "no-3rdparty", "chrome://*/*")
cookies.accept = "no-3rdparty";
prefers_reduced_motion = true;
headers.accept_language = "fr-FR, fr;q=0.9, en-GB;q=0.8, en-US;q=0.7, en;q=0.6";
tls.certificate_errors = "ask-block-thirdparty";
};
editor.command = [ "${pkgs.neovide}/bin/neovide" "--" "-f" "{file}" "-c" "normal {line}G{column0}l" ];
# TODO Doesn't work on Arch. Does it even load the right profile on Nix?
# TODO spellcheck.languages = ["fr-FR" "en-GB" "en-US"];
};
};
# Terminal
alacritty = {
# TODO Emojis. Or maybe they work on NixOS?
# Arch (working) shows this with alacritty -vvv:
# [TRACE] [crossfont] Got font path="/usr/share/fonts/twemoji/twemoji.ttf", index=0
# [DEBUG] [crossfont] Loaded Face Face { ft_face: Font Face: Regular, load_flags: MONOCHROME | TARGET_MONO | COLOR, render_mode: "Mono", lcd_filter: 1 }
# Nix (not working) shows this:
# [TRACE] [crossfont] Got font path="/nix/store/872g3w9vcr5nh93r0m83a3yzmpvd2qrj-home-manager-path/share/fonts/truetype/TwitterColorEmoji-SVGinOT.ttf", index=0
# [DEBUG] [crossfont] Loaded Face Face { ft_face: Font Face: Regular, load_flags: TARGET_LIGHT | COLOR, render_mode: "Lcd", lcd_filter: 1 }
enable = true;
settings = {
bell = {
animation = "EaseOutExpo";
color = "#000000";
command = { program = "${pkgs.sox}/bin/play"; args = [ "-n" "synth" "sine" "C5" "sine" "E4" "remix" "1-2" "fade" "0.1" "0.2" "0.1" ]; };
duration = 100;
};
cursor = { vi_mode_style = "Underline"; };
env = {
WINIT_X11_SCALE_FACTOR = "1";
# Prevents Alacritty from resizing from one monitor to another.
# Might cause issue on HiDPI screens but we'll get there when we get there
};
hints = {
enabled = [
{
binding = { mods = "Control|Alt"; key = "F"; };
command = "${pkgs.xdg-utils}/bin/xdg-open";
mouse = { enabled = true; mods = "Control"; };
post_processing = true;
regex = "(mailto:|gemini:|gopher:|https:|http:|news:|file:|git:|ssh:|ftp:)[^\\u0000-\\u001F\\u007F-\\u009F<>\"\\\\s{-}\\\\^`]+";
}
];
};
key_bindings = [
{ mode = "~Search"; mods = "Alt|Control"; key = "Space"; action = "ToggleViMode"; }
{ mode = "Vi|~Search"; mods = "Control"; key = "K"; action = "ScrollHalfPageUp"; }
{ mode = "Vi|~Search"; mods = "Control"; key = "J"; action = "ScrollHalfPageDown"; }
{ mode = "~Vi"; mods = "Control|Alt"; key = "V"; action = "Paste"; }
{ mods = "Control|Alt"; key = "C"; action = "Copy"; }
{ mode = "~Search"; mods = "Control|Alt"; key = "F"; action = "SearchForward"; }
{ mode = "~Search"; mods = "Control|Alt"; key = "B"; action = "SearchBackward"; }
{ mode = "Vi|~Search"; mods = "Control|Alt"; key = "C"; action = "ClearSelection"; }
];
window = {
dynamic_padding = false;
dynamic_title = true;
};
};
};
# Backup terminal
urxvt = {
enable = true;
package = pkgs.rxvt-unicode-emoji;
scroll = {
bar.enable = false;
};
iso14755 = false; # Disable Ctrl+Shift default bindings
keybindings = {
"Shift-Control-C" = "eval:selection_to_clipboard";
"Shift-Control-V" = "eval:paste_clipboard";
# TODO Not sure resizing works, Nix doesn't have the package (urxvt-resize-font-git on Arch)
"Control-KP_Subtract" = "resize-font:smaller";
"Control-KP_Add" = "resize-font:bigger";
};
extraConfig = {
"letterSpace" = 0;
"perl-ext-common" = "resize-font,bell-command,readline,selection";
"bell-command" = "${pkgs.sox}/bin/play -n synth sine C5 sine E4 remix 1-2 fade 0.1 0.2 0.1 &> /dev/null";
};
};
rofi = {
# TODO This theme template, that was used for Arch, looks much better:
# https://gitlab.com/jordiorlando/base16-rofi/-/blob/master/templates/default.mustache
enable = true;
pass.enable = true;
extraConfig = {
lazy-grab = false;
matching = "regex";
};
};
autorandr = {
enable = true;
hooks.postswitch = {
background = "${pkgs.feh}/bin/feh --no-fehbg --bg-fill ${config.stylix.image}";
};
};
mpv = {
enable = true;
config = {
audio-display = false;
save-position-on-quit = true;
osc = false; # Required by thumbnail script
# Hardware acceleration (from https://nixos.wiki/wiki/Accelerated_Video_Playback#MPV)
hwdec = "auto-safe";
vo = "gpu";
profile = "gpu-hq";
};
scripts = with pkgs.mpvScripts; [ thumbnail ];
scriptOpts = {
mpv_thumbnail_script = {
autogenerate = false; # TODO It creates too many processes at once, crashing the system
cache_directory = "/tmp/mpv_thumbs_${config.home.username}";
mpv_hwdec = "auto-safe";
};
};
};
};
xdg = {
mimeApps = {
enable = true;
defaultApplications = {
"text/html" = "org.qutebrowser.qutebrowser.desktop";
"x-scheme-handler/http" = "org.qutebrowser.qutebrowser.desktop";
"x-scheme-handler/https" = "org.qutebrowser.qutebrowser.desktop";
"x-scheme-handler/about" = "org.qutebrowser.qutebrowser.desktop";
"x-scheme-handler/unknown" = "org.qutebrowser.qutebrowser.desktop";
};
};
userDirs = {
enable = true; # TODO Which ones do we want?
createDirectories = true;
# French, because then it there's a different initial for each, making navigation easier
desktop = null;
download = "${config.home.homeDirectory}/Téléchargements";
music = "${config.home.homeDirectory}/Musiques";
pictures = "${config.home.homeDirectory}/Images";
publicShare = null;
templates = null;
videos = "${config.home.homeDirectory}/Vidéos";
extraConfig = {
XDG_SCREENSHOTS_DIR = "${config.home.homeDirectory}/Screenshots";
};
};
configFile = {
"pulse/client.conf" = {
text = ''cookie-file = .config/pulse/pulse-cookie'';
};
"rofimoji.rc" = {
text = ''
skin-tone = neutral
files = [emojis, math]
action = clipboard
'';
};
"vimpc/vimpcrc" = {
text = ''
map FF :browse<C-M>gg/
map à :set add next<C-M>a:set add end<C-M>
map @ :set add next<C-M>a:set add end<C-M>:next<C-M>
map ° D:browse<C-M>A:shuffle<C-M>:play<C-M>:playlist<C-M>
set songformat {%a - %b: %t}|{%f}$E$R $H[$H%l$H]$H
set libraryformat %n \| {%t}|{%f}$E$R $H[$H%l$H]$H
set ignorecase
set sort library
'';
};
};
};
services = {
blueman-applet.enable = true;
unclutter.enable = true;
dunst =
{
enable = true;
settings =
# TODO Change dmenu for rofi, so we can use context
with config.lib.stylix.colors.withHashtag; {
global = {
separator_color = lib.mkForce base05;
idle_threshold = 120;
markup = "full";
max_icon_size = 48;
# TODO Those shortcuts don't seem to work, maybe try:
# > define shortcuts inside your window manager and bind them to dunstctl(1) commands
close_all = "ctrl+mod4+n";
close = "mod4+n";
context = "mod1+mod4+n";
history = "shift+mod4+n";
};
urgency_low = {
background = lib.mkForce base01;
foreground = lib.mkForce base03;
frame_color = lib.mkForce base05;
};
urgency_normal = {
background = lib.mkForce base02;
foreground = lib.mkForce base05;
frame_color = lib.mkForce base05;
};
urgency_critical = {
background = lib.mkForce base08;
foreground = lib.mkForce base06;
frame_color = lib.mkForce base05;
};
};
};
mpd = {
enable = true;
network = {
listenAddress = "0.0.0.0"; # So it can be controlled from home
# TODO ... and whoever is the Wi-Fi network I'm using, which, not great
startWhenNeeded = true;
};
extraConfig = ''
restore_paused "yes"
'';
};
autorandr.enable = true;
};
home = {
packages = with pkgs; [
pavucontrol # Because can't use Win+F1X on Pinebook 🙃
# remote
tigervnc
# music
mpc-cli
ashuffle
vimpc
# multimedia common
gimp
inkscape
libreoffice
# data management
freefilesync
# browsers
firefox
# fonts
dejavu_fonts
twemoji-color-font
gnome.gedit
feh
zbar
zathura
meld
python3Packages.magic
# x11-exclusive
numlockx
simplescreenrecorder
trayer
xclip
keynav
xorg.xinit
# TODO Make this clean. Service?
# organisation
pass
thunderbird
];
sessionVariables = {
MPD_PORT = "${toString config.services.mpd.network.port}";
ALSA_PLUGIN_DIR = "${pkgs.alsa-plugins}/lib/alsa-lib"; # Fixes an issue with sox (Cannot open shared library libasound_module_pcm_pulse.so)
# UPST Patch this upstream like: https://github.com/NixOS/nixpkgs/blob/216b111fb87091632d077898df647d1438fc2edb/pkgs/applications/audio/espeak-ng/default.nix#L84
};
};
};
}

View file

@ -1,38 +0,0 @@
{ pkgs, lib, config, ... }:
let
pactl = "exec ${pkgs.pulseaudio}/bin/pactl"; # TODO Use NixOS package if using NixOS
mod = config.xsession.windowManager.i3.config.modifier;
in
{
config = lib.mkIf config.frogeye.desktop.xorg {
home = {
packages = with pkgs; [
pavucontrol # Because can't use Win+F1X on Pinebook 🙃
sox
];
sessionVariables = {
ALSA_PLUGIN_DIR = "${pkgs.alsa-plugins}/lib/alsa-lib"; # Fixes an issue with sox (Cannot open shared library libasound_module_pcm_pulse.so)
# UPST Patch this upstream like: https://github.com/NixOS/nixpkgs/blob/216b111fb87091632d077898df647d1438fc2edb/pkgs/applications/audio/espeak-ng/default.nix#L84
};
};
programs.bash.shellAliases = {
beep = ''${pkgs.sox}/bin/play -n synth sine E5 sine A4 remix 1-2 fade 0.5 1.2 0.5 2> /dev/null'';
noise = ''${pkgs.sox}/bin/play -c 2 -n synth $'' + ''{1}noise'';
};
xdg.configFile = {
"pulse/client.conf" = {
text = ''cookie-file = .config/pulse/pulse-cookie'';
};
};
xsession.windowManager.i3.config.keybindings =
{
"XF86AudioRaiseVolume" = "${pactl} set-sink-mute @DEFAULT_SINK@ false; ${pactl} set-sink-volume @DEFAULT_SINK@ +5%";
"XF86AudioLowerVolume" = "${pactl} set-sink-mute @DEFAULT_SINK@ false; ${pactl} set-sink-volume @DEFAULT_SINK@ -5%";
"XF86AudioMute" = "${pactl} set-sink-mute @DEFAULT_SINK@ true";
"${mod}+F7" = "${pactl} suspend-sink @DEFAULT_SINK@ 1; ${pactl} suspend-sink @DEFAULT_SINK@ 0"; # Re-synchronize bluetooth headset
"${mod}+F11" = "exec ${pkgs.pavucontrol}/bin/pavucontrol";
"${mod}+F12" = "exec ${pkgs.pavucontrol}/bin/pavucontrol";
# TODO Find pacmixer?
};
};
}

View file

@ -1,32 +0,0 @@
{ pkgs, lib, config, ... }:
let
builtin_configs = [ "off" "common" "clone-largest" "horizontal" "vertical" "horizontal-reverse" "vertical-reverse" ];
autorandrmenu = { title, option, builtin ? false }: pkgs.writeShellScript "autorandrmenu"
''
shopt -s nullglob globstar
profiles="${if builtin then lib.strings.concatLines builtin_configs else ""}$(${pkgs.autorandr}/bin/autorandr | ${pkgs.gawk}/bin/awk '{ print $1 }')"
profile="$(echo "$profiles" | ${config.programs.rofi.package}/bin/rofi -dmenu -p "${title}")"
[[ -n "$profile" ]] || exit
${pkgs.autorandr}/bin/autorandr ${option} "$profile"
'';
in
{
config = lib.mkIf config.frogeye.desktop.xorg {
frogeye.desktop.i3.bindmodes = {
"Screen setup [A] Auto [L] Load [S] Save [R] Remove [D] Default" =
{
bindings = {
"a" = "exec ${pkgs.autorandr}/bin/autorandr --change --force, mode default";
"l" = "exec ${autorandrmenu {title="Load profile"; option="--load"; builtin = true;}}, mode default";
"s" = "exec ${autorandrmenu {title="Save profile"; option="--save";}}, mode default";
"r" = "exec ${autorandrmenu {title="Remove profile"; option="--remove";}}, mode default";
"d" = "exec ${autorandrmenu {title="Default profile"; option="--default"; builtin = true;}}, mode default";
};
mod_enter = "t";
};
};
programs.autorandr.enable = true;
services.autorandr.enable = true;
};
}
# TODO Deterministic configs?

View file

@ -1,9 +0,0 @@
{ pkgs, config, lib, ... }:
{
config = {
# This correctly sets the background on some occasions, below does the rest
programs.autorandr.hooks.postswitch = {
background = "${pkgs.feh}/bin/feh --no-fehbg --bg-fill ${config.stylix.image}";
};
};
}

View file

@ -1,178 +0,0 @@
{ pkgs, lib, config, nur, ... }:
{
config = lib.mkIf config.frogeye.desktop.xorg {
home.sessionVariables = {
BROWSER = "qutebrowser";
};
programs = {
firefox = {
enable = true;
package = pkgs.firefox.override {
nativeMessagingHosts = [
pkgs.tridactyl-native
];
};
profiles.hm = {
extensions = with config.nur.repos.rycee.firefox-addons;
[
(buildFirefoxXpiAddon {
pname = "onetab";
version = "0.1.0";
addonId = "onetab@nated";
url = "https://addons.mozilla.org/firefox/downloads/file/4118712/one_tab_per_window-0.1.0.xpi";
sha256 = "sha256-64DeL2xgXpqz32LJWDx4jhS2Fvbld8re3z8fdwnNTw0=";
meta = with lib;
{
homepage = "https://git.sr.ht/~nated/onetab";
description = "When a new tab is opened, redirects it to a new window instead.";
license = licenses.unfree;
mozPermissions = [ "tabs" ];
platforms = platforms.all;
};
})
tridactyl
ublock-origin
];
search = {
default = "DuckDuckGo";
engines = {
# TODO Harmonize with qutebrowser search engines
"Nix Packages" = {
urls = [
{
template = "https://search.nixos.org/packages";
params = [
{ name = "type"; value = "packages"; }
{ name = "query"; value = "{searchTerms}"; }
];
}
];
icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
definedAliases = [ "@np" ];
};
"NixOS Wiki" = {
urls = [{ template = "https://nixos.wiki/index.php?search={searchTerms}"; }];
iconUpdateURL = "https://nixos.wiki/favicon.png";
updateInterval = 24 * 60 * 60 * 1000; # every day
definedAliases = [ "@nw" ];
};
"Bing".metaData.hidden = true;
"Google".metaData.alias = "@g"; # builtin engines only support specifying one additional alias
};
force = true;
};
settings = {
"browser.startup.homepage" = "https://geoffrey.frogeye.fr/home.php";
"signon.rememberSignons" = false; # Don't save passwords
"browser.newtabpage.enabled" = false; # Best would be homepage but not possible without extension?
# Europe please
"browser.search.region" = "GB";
"browser.search.isUS" = false;
"distribution.searchplugins.defaultLocale" = "en-GB";
"general.useragent.locale" = "en-GB";
};
};
};
qutebrowser = {
enable = true;
keyBindings = {
normal = {
# Match tab behaviour to i3. Not that I use tabs.
"H" = "tab-prev";
"J" = "back";
"K" = "forward";
"L" = "tab-next";
# "T" = null;
"af" = "spawn --userscript freshrss"; # TODO Broken?
"as" = "spawn --userscript shaarli"; # TODO I don't use shaarli anymore
# "d" = null;
"u" = "undo --window";
# TODO Unbind d and T (?)
};
};
loadAutoconfig = true;
searchEngines = rec {
DEFAULT = ecosia;
alpinep = "https://pkgs.alpinelinux.org/packages?name={}&branch=edge";
ampwhat = "http://www.amp-what.com/unicode/search/{}";
arch = "https://wiki.archlinux.org/?search={}";
archp = "https://www.archlinux.org/packages/?q={}";
aur = "https://aur.archlinux.org/packages/?K={}";
aw = ampwhat;
ddg = duckduckgo;
dockerhub = "https://hub.docker.com/search/?isAutomated=0&isOfficial=0&page=1&pullCount=0&q={}&starCount=0";
duckduckgo = "https://duckduckgo.com/?q={}&ia=web";
ecosia = "https://www.ecosia.org/search?q={}";
gfr = "https://www.google.fr/search?hl=fr&q={}";
g = google;
gh = github;
gi = "http://images.google.com/search?q={}";
giphy = "https://giphy.com/search/{}";
github = "https://github.com/search?q={}";
google = "https://www.google.fr/search?q={}";
hm = homemanager;
homemanager = "https://home-manager-options.extranix.com/?query={}&release=${config.home.version.release}";
invidious = "https://invidious.frogeye.fr/search?q={}";
inv = invidious;
nixos = "https://search.nixos.org/options?channel=${config.home.version.release}&query={}";
nixoswiki = "https://wiki.nixos.org/w/index.php?search={}";
nixpkgs = "https://search.nixos.org/packages?channel=${config.home.version.release}&query={}";
noogle = "https://noogle.dev/q?term={}";
npm = "https://www.npmjs.com/search?q={}";
nw = nixoswiki;
os = nixos;
pkgs = nixpkgs;
q = qwant;
qwant = "https://www.qwant.com/?t=web&q={}";
wolfram = "https://www.wolframalpha.com/input/?i={}";
youtube = "https://www.youtube.com/results?search_query={}";
yt = youtube;
};
settings = {
downloads.location.prompt = false;
tabs = {
show = "never";
tabs_are_windows = true;
};
url = rec {
open_base_url = true;
start_pages = lib.mkDefault "https://geoffrey.frogeye.fr/blank.html";
default_page = start_pages;
};
content = {
# I had this setting below, not sure if it did something special
# config.set("content.cookies.accept", "no-3rdparty", "chrome://*/*")
cookies.accept = "no-3rdparty";
prefers_reduced_motion = true;
headers.accept_language = "fr-FR, fr;q=0.9, en-GB;q=0.8, en-US;q=0.7, en;q=0.6";
tls.certificate_errors = "ask-block-thirdparty";
};
editor.command = [ "${pkgs.neovide}/bin/neovide" "--" "-f" "{file}" "-c" "normal {line}G{column0}l" ];
# TODO Doesn't work on Arch. Does it even load the right profile on Nix?
# TODO spellcheck.languages = ["fr-FR" "en-GB" "en-US"];
};
};
};
xdg = {
configFile."tridactyl/tridactylrc".source = ./tridactylrc; # TODO Improve that :)
mimeApps = {
enable = true;
defaultApplications = {
"text/html" = "org.qutebrowser.qutebrowser.desktop";
"x-scheme-handler/http" = "org.qutebrowser.qutebrowser.desktop";
"x-scheme-handler/https" = "org.qutebrowser.qutebrowser.desktop";
"x-scheme-handler/about" = "org.qutebrowser.qutebrowser.desktop";
"x-scheme-handler/unknown" = "org.qutebrowser.qutebrowser.desktop";
};
};
};
xsession.windowManager.i3.config.keybindings = {
"${config.xsession.windowManager.i3.config.modifier}+m" = "exec ${config.programs.qutebrowser.package}/bin/qutebrowser --override-restore";
};
};
imports = [
nur.hmModules.nur
];
}

View file

@ -1,162 +0,0 @@
{ pkgs, config, lib, ... }:
{
imports = [
./audio
./autorandr
./background
./browser
./frobar
./i3.nix
./lock
./mpd
./presentation
./redness
./screenshots
./terminal
];
config = lib.mkIf config.frogeye.desktop.xorg {
xsession = {
enable = true;
# Not using config.xdg.configHome because it needs to be $HOME-relative paths and path manipulation is hard
scriptPath = ".config/xsession";
profilePath = ".config/xprofile";
windowManager = {
i3.enable = true;
};
numlock.enable = config.frogeye.desktop.numlock;
};
programs = {
# Terminal
bash.shellAliases = {
x = "startx ${config.home.homeDirectory}/${config.xsession.scriptPath}; logout";
lmms = "lmms --config ${config.xdg.configHome}/lmmsrc.xml";
};
rofi = {
# TODO This theme template, that was used for Arch, looks much better:
# https://gitlab.com/jordiorlando/base16-rofi/-/blob/master/templates/default.mustache
enable = true;
pass.enable = true;
extraConfig = {
lazy-grab = false;
matching = "regex";
};
};
mpv = {
enable = true;
config = {
audio-display = false;
save-position-on-quit = true;
osc = false; # Required by thumbnail script
# Hardware acceleration (from https://nixos.wiki/wiki/Accelerated_Video_Playback#MPV, vo=gpu already default)
hwdec = "auto-safe";
profile = "gpu-hq";
};
scripts = with pkgs.mpvScripts; [ thumbnail ];
scriptOpts = {
mpv_thumbnail_script = {
autogenerate = false; # TODO It creates too many processes at once, crashing the system
cache_directory = "/tmp/mpv_thumbs_${config.home.username}";
mpv_hwdec = "auto-safe";
};
};
};
};
xdg = {
userDirs = {
enable = true; # TODO Which ones do we want?
createDirectories = true;
# French, because then it there's a different initial for each, making navigation easier
desktop = null;
download = "${config.home.homeDirectory}/Téléchargements";
pictures = "${config.home.homeDirectory}/Images";
publicShare = null;
templates = null;
videos = "${config.home.homeDirectory}/Vidéos";
};
};
services = {
blueman-applet.enable = true;
unclutter.enable = true;
dunst =
{
enable = true;
settings =
# TODO Change dmenu for rofi, so we can use context
with config.lib.stylix.colors.withHashtag; {
global = {
separator_color = lib.mkForce base05;
idle_threshold = 120;
markup = "full";
max_icon_size = 48;
# TODO Those shortcuts don't seem to work, maybe try:
# > define shortcuts inside your window manager and bind them to dunstctl(1) commands
close_all = "ctrl+mod4+n";
close = "mod4+n";
context = "mod1+mod4+n";
history = "shift+mod4+n";
};
urgency_low = {
background = lib.mkForce base01;
foreground = lib.mkForce base03;
frame_color = lib.mkForce base05;
};
urgency_normal = {
background = lib.mkForce base02;
foreground = lib.mkForce base05;
frame_color = lib.mkForce base05;
};
urgency_critical = {
background = lib.mkForce base08;
foreground = lib.mkForce base06;
frame_color = lib.mkForce base05;
};
};
};
};
home = {
file = {
".face" = {
# TODO Only works on pindakaas? See https://wiki.archlinux.org/title/LightDM#Changing_your_avatar
source = pkgs.runCommand "face.png" { } "${pkgs.inkscape}/bin/inkscape ${./face.svg} -w 1024 -o $out";
};
};
packages = with pkgs; [
# remote
tigervnc
# multimedia common
gimp
inkscape
libreoffice
# data management
freefilesync
# misc
gnome.gedit
xfce.thunar
nomacs
feh
zbar
evince
zathura
meld
python3Packages.magic
# x11-exclusive
simplescreenrecorder
trayer
xclip
keynav
xorg.xinit
];
sessionVariables = {
# XAUTHORITY = "${config.xdg.configHome}/Xauthority"; # Disabled as this causes lock-ups with DMs
};
};
};
}

View file

@ -1,219 +0,0 @@
{ pkgs, lib, config, ... }:
let
# FOCUS
focus = "exec ${ pkgs.writeShellScript "i3-focus-window" ''
WINDOW=`${pkgs.xdotool}/bin/xdotool getwindowfocus`
eval `${pkgs.xdotool}/bin/xdotool getwindowgeometry --shell $WINDOW` # this brings in variables WIDTH and HEIGHT
TX=`${pkgs.coreutils}/bin/expr $WIDTH / 2`
TY=`${pkgs.coreutils}/bin/expr $HEIGHT / 2`
${pkgs.xdotool}/bin/xdotool mousemove -window $WINDOW $TX $TY
''
}";
# CARDINALS
cardinals = [
{ vi = "h"; arrow = "Left"; container = "left"; workspace = "prev_on_output"; output = "left"; }
{ vi = "l"; arrow = "Right"; container = "right"; workspace = "next_on_output"; output = "right"; }
{ vi = "j"; arrow = "Down"; container = "up"; workspace = "prev"; output = "below"; }
{ vi = "k"; arrow = "Up"; container = "down"; workspace = "next"; output = "above"; }
];
forEachCardinal = f: map (c: f c) cardinals;
# WORKSPACES
workspaces_keys = lib.strings.stringToCharacters "1234567890";
workspaces = map
(i: {
id = i;
name = builtins.toString (i + 1);
key = builtins.elemAt workspaces_keys i;
})
(lib.lists.range 0 ((builtins.length workspaces_keys) - 1));
forEachWorkspace = f: map (w: f w) workspaces;
# MISC
mod = config.xsession.windowManager.i3.config.modifier;
rofi = "exec --no-startup-id ${config.programs.rofi.package}/bin/rofi";
modes = config.frogeye.desktop.i3.bindmodes;
x11_screens = config.frogeye.desktop.x11_screens;
in
{
config = lib.mkIf config.xsession.windowManager.i3.enable {
stylix.targets.i3.enable = false;
xdg.configFile = {
"rofimoji.rc" = {
text = ''
skin-tone = neutral
files = [emojis, math]
action = clipboard
'';
};
};
xsession.windowManager.i3.config = {
modifier = "Mod4";
fonts = {
names = [ config.stylix.fonts.sansSerif.name ];
};
terminal = "alacritty";
colors = let ignore = "#ff00ff"; in
with config.lib.stylix.colors.withHashtag; lib.mkForce {
focused = { border = base0B; background = base0B; text = base00; indicator = base00; childBorder = base0B; };
focusedInactive = { border = base02; background = base02; text = base05; indicator = base02; childBorder = base02; };
unfocused = { border = base05; background = base04; text = base00; indicator = base04; childBorder = base00; };
urgent = { border = base0F; background = base08; text = base00; indicator = base08; childBorder = base0F; };
placeholder = { border = ignore; background = base00; text = base05; indicator = ignore; childBorder = base00; };
background = base07;
# I set the color of the active tab as the the background color of the terminal so they merge together.
};
focus.followMouse = false;
keybindings =
{
# Compatibility layer for people coming from other backgrounds
"Mod1+Tab" = "${rofi} -modi window -show window";
"Mod1+F2" = "${rofi} -modi drun -show drun";
"Mod1+F4" = "kill";
# kill focused window
"${mod}+z" = "kill";
button2 = "kill";
# Rofi
"${mod}+i" = "exec --no-startup-id ${pkgs.rofimoji}/bin/rofimoji";
"${mod}+Tab" = "${rofi} -modi window -show window";
# start program launcher
"${mod}+d" = "${rofi} -modi run -show run";
"${mod}+Shift+d" = "${rofi} -modi drun -show drun";
# Start Applications
"${mod}+p" = "exec ${pkgs.xfce.thunar}/bin/thunar";
# Misc
"${mod}+F10" = "exec ${ pkgs.writeShellScript "show-keyboard-layout"
''
layout=`${pkgs.xorg.setxkbmap}/bin/setxkbmap -query | ${pkgs.gnugrep}/bin/grep ^layout: | ${pkgs.gawk}/bin/awk '{ print $2 }'`
${pkgs.libgnomekbd}/bin/gkbd-keyboard-display -l $layout
''
}";
# workspace back and forth (with/without active container)
"${mod}+b" = "workspace back_and_forth; ${focus}";
"${mod}+Shift+b" = "move container to workspace back_and_forth; workspace back_and_forth; ${focus}";
# Change container layout
"${mod}+g" = "split h; ${focus}";
"${mod}+v" = "split v; ${focus}";
"${mod}+f" = "fullscreen toggle; ${focus}";
"${mod}+s" = "layout stacking; ${focus}";
"${mod}+w" = "layout tabbed; ${focus}";
"${mod}+e" = "layout toggle split; ${focus}";
"${mod}+Shift+space" = "floating toggle; ${focus}";
# Focus container
"${mod}+space" = "focus mode_toggle; ${focus}";
"${mod}+a" = "focus parent; ${focus}";
"${mod}+q" = "focus child; ${focus}";
# i3 control
"${mod}+Shift+c" = "reload";
"${mod}+Shift+r" = "restart";
"${mod}+Shift+e" = "exit";
} // lib.mapAttrs' (k: v: lib.nameValuePair v.enter "mode ${v.name}") (lib.filterAttrs (k: v: v.enter != null) modes)
// lib.attrsets.mergeAttrsList (forEachCardinal (c: {
# change focus
"${mod}+${c.vi}" = "focus ${c.container}; ${focus}";
# move focused window
"${mod}+Shift+${c.vi}" = "move ${c.container}; ${focus}";
#navigate workspaces next / previous
"${mod}+Ctrl+${c.vi}" = "workspace ${c.workspace}; ${focus}";
# Move to workspace next / previous with focused container
"${mod}+Ctrl+Shift+${c.vi}" = "move container to workspace ${c.workspace}; workspace ${c.workspace}; ${focus}";
# move workspaces to screen (arrow keys)
"${mod}+Ctrl+Shift+${c.arrow}" = "move workspace to output ${c.output}; ${focus}";
})) // lib.attrsets.mergeAttrsList (forEachWorkspace (w: {
# Switch to workspace
"${mod}+${w.key}" = "workspace ${w.name}; ${focus}";
# move focused container to workspace
"${mod}+ctrl+${w.key}" = "move container to workspace ${w.name}; ${focus}";
# move to workspace with focused container
"${mod}+shift+${w.key}" = "move container to workspace ${w.name}; workspace ${w.name}; ${focus}";
}));
modes = lib.mapAttrs'
(k: v: lib.nameValuePair v.name (v.bindings // lib.optionalAttrs v.return_bindings {
"Return" = "mode default";
"Escape" = "mode default";
}))
modes;
window = {
hideEdgeBorders = "both";
titlebar = false; # So that single-container screens are basically almost fullscreen
commands = [
# switch to workspace with urgent window automatically
{ criteria = { urgent = "latest"; }; command = "focus"; }
];
};
floating = {
criteria = [
{ window_role = "pop-up"; }
{ window_role = "task_dialog"; }
];
};
startup = [
{
notification = false;
command = "${pkgs.writeShellApplication {
name = "batteryNotify";
runtimeInputs = with pkgs; [coreutils libnotify];
text = builtins.readFile ./batteryNotify.sh;
# TODO Use batsignal instead?
# TODO Only on computers with battery
}}/bin/batteryNotify";
}
];
workspaceLayout = "tabbed";
focus.mouseWarping = true; # i3 only supports warping to workspace, hence ${focus}
workspaceOutputAssign =
forEachWorkspace (w: { output = builtins.elemAt x11_screens (lib.mod w.id (builtins.length x11_screens)); workspace = w.name; });
};
frogeye.desktop.i3.bindmodes = {
"Resize" = {
bindings = {
"h" = "resize shrink width 10 px or 10 ppt; ${focus}";
"j" = "resize grow height 10 px or 10 ppt; ${focus}";
"k" = "resize shrink height 10 px or 10 ppt; ${focus}";
"l" = "resize grow width 10 px or 10 ppt; ${focus}";
};
mod_enter = "r";
};
"[L] Vérouillage [E] Déconnexion [S] Veille [H] Hibernation [R] Redémarrage [P] Extinction" = {
bindings = {
"l" = "exec --no-startup-id exec xlock, mode default";
"e" = "exit, mode default";
"s" = "exec --no-startup-id exec xlock & ${pkgs.systemd}/bin/systemctl suspend --check-inhibitors=no, mode default";
"h" = "exec --no-startup-id exec xlock & ${pkgs.systemd}/bin/systemctl hibernate, mode default";
"r" = "exec --no-startup-id ${pkgs.systemd}/bin/systemctl reboot, mode default";
"p" = "exec --no-startup-id ${pkgs.systemd}/bin/systemctl poweroff -i, mode default";
};
mod_enter = "Escape";
};
};
};
options = {
frogeye.desktop.i3.bindmodes = lib.mkOption {
default = { };
type = lib.types.attrsOf (lib.types.submodule ({ config, name, ... }: {
options = {
name = lib.mkOption {
type = lib.types.str;
default = name;
};
bindings = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
default = { };
};
enter = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = "${mod}+${config.mod_enter}";
};
mod_enter = lib.mkOption {
type = lib.types.str;
};
return_bindings = lib.mkOption {
type = lib.types.bool;
default = true;
};
};
}));
};
};
}

View file

@ -1,56 +0,0 @@
{ pkgs, lib, config, ... }:
let
# lockColors = with config.lib.stylix.colors.withHashtag; { a = base00; b = base01; d = base00; }; # Black or White, depending on current theme
# lockColors = with config.lib.stylix.colors.withHashtag; { a = base0A; b = base0B; d = base00; }; # Green + Yellow
lockColors = { a = "#82a401"; b = "#466c01"; d = "#648901"; }; # Old
lockSvg = pkgs.writeText "lock.svg" ''
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" height="50" width="50">
<path fill="${lockColors.a}" d="M0 50h50V0H0z"/>
<path d="M0 0l50 50H25L0 25zm50 0v25L25 0z" fill="${lockColors.b}"/>
</svg>
'';
lockPng = pkgs.runCommand "lock.png" { } "${pkgs.imagemagick}/bin/convert ${lockSvg} $out";
mod = config.xsession.windowManager.i3.config.modifier;
in
{
config = lib.mkIf config.frogeye.desktop.xorg {
home.packages = with pkgs; [
(pkgs.writeShellApplication {
name = "xlock";
text = ''
${config.frogeye.hooks.lock}
# TODO Reevaluate whether we want this or not
if ! ${pkgs.lightdm}/bin/dm-tool lock
then
if [ -d ${config.xdg.cacheHome}/lockpatterns ]
then
pattern=$(${pkgs.findutils} ${config.xdg.cacheHome}/lockpatterns | sort -R | head -1)
else
pattern=${lockPng}
fi
revert() {
${pkgs.xorg.xset}/bin/xset dpms 0 0 0
}
trap revert SIGHUP SIGINT SIGTERM
${pkgs.xorg.xset}/bin/xset dpms 5 5 5
${pkgs.i3lock}/bin/i3lock --nofork --color ${builtins.substring 1 6 lockColors.d} --image="$pattern" --tiling --ignore-empty-password
revert
fi
'';
})
];
xsession.windowManager.i3.config = {
keybindings = {
# Screen off commands
"${mod}+F1" = "--release exec --no-startup-id ${pkgs.xorg.xset}/bin/xset dpms force off";
"${mod}+F4" = "exec --no-startup-id ${pkgs.xautolock}/bin/xautolock -disable";
"${mod}+F5" = "exec --no-startup-id ${pkgs.xautolock}/bin/xautolock -enable";
};
startup = [
# Stop screen after 10 minutes, 1 minutes after lock it
{ notification = false; command = "${pkgs.xautolock}/bin/xautolock -time 10 -locker '${pkgs.xorg.xset}/bin/xset dpms force standby' -killtime 1 -killer xlock"; }
# services.screen-locker.xautolock is hardcoded to use systemd for -locker (doesn't even work...)
];
};
};
}

View file

@ -1,48 +0,0 @@
{ pkgs, lib, config, ... }:
{
config = lib.mkIf config.frogeye.desktop.xorg {
home = {
packages = with pkgs; [
ashuffle
mpc-cli
vimpc
];
sessionVariables = {
MPD_PORT = "${toString config.services.mpd.network.port}";
};
};
services.mpd = {
enable = true;
network = {
listenAddress = "0.0.0.0"; # Can be controlled remotely, determined with firewall
startWhenNeeded = true;
};
extraConfig = ''
restore_paused "yes"
'';
};
xdg = {
configFile = {
"vimpc/vimpcrc" = {
text = ''
map FF :browse<C-M>gg/
map à :set add next<C-M>a:set add end<C-M>
map @ :set add next<C-M>a:set add end<C-M>:next<C-M>
map ° D:browse<C-M>A:shuffle<C-M>:play<C-M>:playlist<C-M>
set songformat {%a - %b: %t}|{%f}$E$R $H[$H%l$H]$H
set libraryformat %n \| {%t}|{%f}$E$R $H[$H%l$H]$H
set ignorecase
set sort library
'';
};
};
userDirs.music = "${config.home.homeDirectory}/Musiques";
};
xsession.windowManager.i3.config.keybindings =
{
"XF86AudioPrev" = "exec ${pkgs.mpc-cli}/bin/mpc prev";
"XF86AudioPlay" = "exec ${pkgs.mpc-cli}/bin/mpc toggle";
"XF86AudioNext" = "exec ${pkgs.mpc-cli}/bin/mpc next";
};
};
}

View file

@ -1,39 +0,0 @@
# Dual-screen presenting for slideshows and stuff.
# Not tested since Nix.
# Config mentions pdfpc, although the last thing I used was Impressive, even made patches to it.
# UPST Add Impressive to nixpkgs
{ pkgs, lib, config, ... }:
let
mode_pres_main = "Presentation (main display)";
mode_pres_sec = "Presentation (secondary display)";
in
{
config = lib.mkIf config.frogeye.desktop.xorg {
frogeye.desktop.i3.bindmodes = {
"${mode_pres_main}" = {
mod_enter = "Shift+p";
bindings = {
"b" = "workspace 3, workspace 4, mode ${mode_pres_sec}";
"q" = "mode default";
"Return" = "mode default";
};
return_bindings = false;
};
"${mode_pres_sec}" = {
enter = null;
bindings = {
"b" = "workspace 1, workspace 2, mode ${mode_pres_main}";
"q" = "mode default";
"Return" = "mode default";
};
return_bindings = false;
};
};
xsession.windowManager.i3.config.window.commands = [
# Open specific applications in floating mode
{ criteria = { title = "^pdfpc.*"; window_role = "presenter"; }; command = "move to output left, fullscreen"; }
{ criteria = { title = "^pdfpc.*"; window_role = "presentation"; }; command = "move to output right, fullscreen"; }
];
};
}

View file

@ -1,28 +0,0 @@
{ pkgs, lib, config, ... }:
let
# UPST
sct = pkgs.sct.overrideAttrs
(old: {
patches = (old.patches or [ ]) ++ [
./sct_aarch64.patch
];
});
in
{
config = lib.mkIf config.frogeye.desktop.xorg {
frogeye.desktop.i3.bindmodes = {
"Temperature [R] Red [D] Dust storm [C] Campfire [O] Normal [A] All nighter [B] Blue" = {
bindings = {
"r" = "exec ${sct}/bin/sct 1000";
"d" = "exec ${sct}/bin/sct 2000";
"c" = "exec ${sct}/bin/sct 4500";
"o" = "exec ${sct}/bin/sct";
"a" = "exec ${sct}/bin/sct 8000";
"b" = "exec ${sct}/bin/sct 10000";
};
mod_enter = "y";
};
};
home.packages = [ sct ];
};
}

View file

@ -1,16 +0,0 @@
{ pkgs, lib, config, ... }:
let
dir = config.xdg.userDirs.extraConfig.XDG_SCREENSHOTS_DIR;
scrot = "${pkgs.scrot}/bin/scrot --exec '${pkgs.coreutils}/bin/mv $f ${dir}/ && ${pkgs.optipng}/bin/optipng ${dir}/$f'";
mod = config.xsession.windowManager.i3.config.modifier;
in
{
config = lib.mkIf config.frogeye.desktop.xorg {
xdg.userDirs.extraConfig.XDG_SCREENSHOTS_DIR = "${config.home.homeDirectory}/Screenshots";
xsession.windowManager.i3.config.keybindings = {
"Print" = "exec ${scrot} --focused";
"${mod}+Print" = "exec ${scrot}";
"Ctrl+Print" = "--release exec ${scrot} --select";
};
};
}

View file

@ -1,90 +0,0 @@
{ pkgs, lib, config, ... }:
let
mod = config.xsession.windowManager.i3.config.modifier;
in
{
config = lib.mkIf config.frogeye.desktop.xorg {
home.sessionVariables = {
RXVT_SOCKET = "${config.xdg.stateHome}/urxvtd";
# We don't use urxvt deamon mode as we use it as a backup, but just in case, this helps keep it out of the home directory.
};
programs = {
alacritty = {
# TODO Emojis
# Arch (working) shows this with alacritty -vvv:
# [TRACE] [crossfont] Got font path="/usr/share/fonts/twemoji/twemoji.ttf", index=0
# [DEBUG] [crossfont] Loaded Face Face { ft_face: Font Face: Regular, load_flags: MONOCHROME | TARGET_MONO | COLOR, render_mode: "Mono", lcd_filter: 1 }
# Nix (not working) shows this:
# [TRACE] [crossfont] Got font path="/nix/store/872g3w9vcr5nh93r0m83a3yzmpvd2qrj-home-manager-path/share/fonts/truetype/TwitterColorEmoji-SVGinOT.ttf", index=0
# [DEBUG] [crossfont] Loaded Face Face { ft_face: Font Face: Regular, load_flags: TARGET_LIGHT | COLOR, render_mode: "Lcd", lcd_filter: 1 }
enable = true;
settings = {
bell = {
animation = "EaseOutExpo";
color = "#000000";
command = { program = "${pkgs.sox}/bin/play"; args = [ "-n" "synth" "sine" "C5" "sine" "E4" "remix" "1-2" "fade" "0.1" "0.2" "0.1" ]; };
duration = 100;
};
cursor = { vi_mode_style = "Underline"; };
env = {
WINIT_X11_SCALE_FACTOR = "1";
# Prevents Alacritty from resizing from one monitor to another.
# Might cause issue on HiDPI screens but we'll get there when we get there
};
hints = {
enabled = [
{
binding = { mods = "Control|Alt"; key = "F"; };
command = "${pkgs.xdg-utils}/bin/xdg-open";
mouse = { enabled = true; mods = "Control"; };
post_processing = true;
regex = "(mailto:|gemini:|gopher:|https:|http:|news:|file:|git:|ssh:|ftp:)[^\\u0000-\\u001F\\u007F-\\u009F<>\"\\\\s{-}\\\\^`]+";
}
];
};
key_bindings = [
{ mode = "~Search"; mods = "Alt|Control"; key = "Space"; action = "ToggleViMode"; }
{ mode = "Vi|~Search"; mods = "Control"; key = "K"; action = "ScrollHalfPageUp"; }
{ mode = "Vi|~Search"; mods = "Control"; key = "J"; action = "ScrollHalfPageDown"; }
{ mode = "~Vi"; mods = "Control|Alt"; key = "V"; action = "Paste"; }
{ mods = "Control|Alt"; key = "C"; action = "Copy"; }
{ mode = "~Search"; mods = "Control|Alt"; key = "F"; action = "SearchForward"; }
{ mode = "~Search"; mods = "Control|Alt"; key = "B"; action = "SearchBackward"; }
{ mode = "Vi|~Search"; mods = "Control|Alt"; key = "C"; action = "ClearSelection"; }
];
window = {
dynamic_padding = false;
dynamic_title = true;
};
};
};
# Backup terminal
urxvt = {
enable = true;
package = pkgs.rxvt-unicode-emoji;
scroll = {
bar.enable = false;
};
iso14755 = false; # Disable Ctrl+Shift default bindings
keybindings = {
"Shift-Control-C" = "eval:selection_to_clipboard";
"Shift-Control-V" = "eval:paste_clipboard";
# TODO Not sure resizing works, Nix doesn't have the package (urxvt-resize-font-git on Arch)
"Control-KP_Subtract" = "resize-font:smaller";
"Control-KP_Add" = "resize-font:bigger";
};
extraConfig = {
"letterSpace" = 0;
"perl-ext-common" = "resize-font,bell-command,readline,selection";
"bell-command" = "${pkgs.sox}/bin/play -n synth sine C5 sine E4 remix 1-2 fade 0.1 0.2 0.1 &> /dev/null";
};
};
};
xsession.windowManager.i3.config.keybindings = {
"${mod}+Return" = "exec ${config.programs.alacritty.package}/bin/alacritty msg create-window -e zsh || exec ${config.programs.alacritty.package}/bin/alacritty -e zsh";
# -e zsh is for systems where I can't configure my user's shell
"${mod}+Shift+Return" = "exec ${config.programs.urxvt.package}/bin/urxvt";
};
};
}

65
hm/dev.nix Normal file
View file

@ -0,0 +1,65 @@
{ pkgs, config, ... }: {
# TODO Maybe should be per-directory dotenv
# Or not, for neovim
# Always on
home.packages = with pkgs; [
# Common
perf-tools
jq
yq
universal-ctags
highlight
# Network
socat
dig
whois
nmap
tcpdump
# nix
nix
# Always on (graphical)
] ++ lib.optionals config.frogeye.desktop.xorg [
# Common
zeal-qt6 # Offline documentation
# Network
wireshark-qt
# Ansible
] ++ lib.optionals config.frogeye.dev.ansible [
ansible
ansible-lint
# C/C++
] ++ lib.optionals config.frogeye.dev.c [
cmake
clang
ccache
gdb
# Docker
] ++ lib.optionals config.frogeye.dev.docker [
docker
docker-compose
# FPGA
] ++ lib.optionals config.frogeye.dev.fpga [
verilog
# ghdl # TODO Not on aarch64
# FPGA (graphical)
] ++ lib.optionals (config.frogeye.desktop.xorg && config.frogeye.dev.fpga) [
yosys
gtkwave
# Python
] ++ lib.optionals config.frogeye.dev.python [
python3Packages.ipython
];
}

View file

@ -1,45 +0,0 @@
{ pkgs, lib, config, ... }:
{
config = lib.mkIf config.frogeye.dev.c {
frogeye = {
direnv = {
CCACHE_DIR = "${config.xdg.cacheHome}/ccache"; # The config file alone seems to be not enough
};
junkhome = [
"binwalk" # Should use .config according to the GitHub code though
"cmake"
"ddd"
"ghidra"
];
};
home = {
packages = with pkgs; [
binwalk
ccache
clang
cmake
ddd
gdb
];
sessionVariables = {
CCACHE_CONFIGPATH = "${config.xdg.configHome}/ccache.conf";
};
};
programs.bash.shellAliases = {
gdb = "gdb -x ${config.xdg.configHome}/gdbinit";
};
programs.nixvim.plugins.dap.enable = true; # Debug Adapter Protocol client
xdg.configFile = {
"ccache.conf" = {
text = "ccache_dir = ${config.xdg.cacheHome}/ccache";
};
gdbinit = {
text = ''
define hook-quit
set confirm off
end
'';
};
};
};
}

View file

@ -1,73 +0,0 @@
{ pkgs, config, ... }: {
# TODO Maybe should be per-directory dotenv
# Or not, for neovim
config = {
# Always on
home.packages = with pkgs; [
# Common
perf-tools
jq
yq
universal-ctags
cloc
# Network
socat
dig
whois
nmap
tcpdump
mtr
traceroute
# nix
nix
# Always on (graphical)
] ++ lib.optionals config.frogeye.desktop.xorg [
# Common
zeal-qt6 # Offline documentation
# Network
wireshark-qt
# Ansible
] ++ lib.optionals config.frogeye.dev.ansible [
ansible
ansible-lint
# Docker
] ++ lib.optionals config.frogeye.dev.docker [
docker
docker-compose
# FPGA
] ++ lib.optionals config.frogeye.dev.fpga [
verilog
] ++ lib.optionals (config.frogeye.dev.fpga && pkgs.stdenv.isx86_64) [
ghdl
# FPGA (graphical)
] ++ lib.optionals (config.frogeye.desktop.xorg && config.frogeye.dev.fpga) [
yosys
gtkwave
];
programs.nixvim.plugins.lsp.servers = {
ansiblels.enable = config.frogeye.dev.ansible; # Ansible
bashls.enable = true; # Bash
jsonls.enable = true; # JSON
lua-ls.enable = true; # Lua (for Neovim debugging)
perlpls.enable = config.frogeye.dev.perl; # Perl
phpactor.enable = config.frogeye.dev.php; # PHP
nixd = {
enable = true;
settings.formatting.command = "nixpkgs-fmt";
};
# TODO Something for SQL. sqls is deprecated, sqlls is not in Nixpkgs. Probably needs a DB connection configured anyways?
yamlls.enable = true; # YAML
# TODO Check out none-ls
};
};
}

View file

@ -1,10 +0,0 @@
{ pkgs, config, ... }: {
imports = [
./c.nix
./common.nix
./go.nix
./node.nix
./prose.nix
./python.nix
];
}

View file

@ -1,19 +0,0 @@
# Untested post-nix
{ pkgs, lib, config, ... }:
{
config = lib.mkIf config.frogeye.dev.go {
frogeye = {
direnv = {
GOPATH = "${config.xdg.cacheHome}/go";
};
};
home = {
packages = with pkgs; [
go
];
sessionPath = [
"${config.home.sessionVariables.GOPATH}"
];
};
};
}

View file

@ -1,21 +0,0 @@
# Untested post-nix
{ pkgs, lib, config, ... }:
{
config = lib.mkIf config.frogeye.dev.node {
frogeye = {
direnv = {
npm_config_cache = "${config.xdg.cacheHome}/npm";
YARN_CACHE_FOLDER = "${config.xdg.cacheHome}/yarn";
};
};
home = {
sessionVariables = {
NODE_REPL_HISTORY = "${config.xdg.cacheHome}/node_repl_history";
YARN_DISABLE_SELF_UPDATE_CHECK = "true"; # This also disable the creation of a ~/.yarnrc file
};
};
programs.bash.shellAliases = {
bower = "bower --config.storage.packages=${config.xdg.cacheHome}/bower/packages --config.storage.registry=${config.xdg.cacheHome}/bower/registry --config.storage.links=${config.xdg.cacheHome}/bower/links";
};
};
}

View file

@ -1,38 +0,0 @@
# Prose is a programming language, fight me
{ pkgs, lib, config, ... }:
{
config = lib.mkIf config.frogeye.dev.prose {
home = {
packages = with pkgs; [
hunspell
hunspellDicts.en_GB-ize
hunspellDicts.en_US
hunspellDicts.fr-moderne
hunspellDicts.nl_NL
# TODO libreoffice-extension-languagetool or libreoffice-extension-grammalecte-fr
];
};
programs.nixvim = {
autoCmd = [
# vim-easy-align: Align Markdown tables with |
{ event = "FileType"; pattern = "markdown"; command = "vmap <Bar> :EasyAlign*<Bar><Enter>"; }
];
extraPlugins = with pkgs.vimPlugins; lib.optionals config.programs.pandoc.enable [
vim-pandoc # Pandoc-specific stuff because there's no LSP for it
vim-pandoc-syntax
];
extraConfigVim = lib.optionalString config.programs.pandoc.enable ''
let g:pandoc#modules#disabled = ["folding"]
let g:pandoc#spell#enabled = 0
let g:pandoc#syntax#conceal#use = 0
'';
plugins.none-ls = {
enable = true;
sources = {
code_actions.ltrs.enable = true;
diagnostics.ltrs.enable = true;
};
};
};
};
}

View file

@ -1,54 +0,0 @@
{ pkgs, lib, config, ... }:
{
config = lib.mkIf config.frogeye.dev.python {
home = {
packages = with pkgs; [
python3
python3Packages.ipython
];
sessionVariables = {
PYTHONSTARTUP = "${config.xdg.configHome}/pythonstartup.py";
};
};
programs.bash.shellAliases = {
ipython = "ipython --no-confirm-exit --pdb";
};
programs.nixvim.plugins.lsp.servers.pylsp = {
# Python
enable = config.frogeye.dev.python;
settings.plugins = {
black.enabled = true;
flake8 = {
enabled = true;
maxLineLength = 88; # Compatibility with Black
};
isort.enabled = true;
mccabe.enabled = true;
pycodestyle = {
enabled = true;
maxLineLength = 88; # Compatibility with Black
};
pyflakes.enabled = true;
pylint.enabled = true;
pylsp_mypy = {
enabled = true;
overrides = [
"--cache-dir=${config.xdg.cacheHome}/mypy"
"--ignore-missing-imports"
"--disallow-untyped-defs"
"--disallow-untyped-calls"
"--disallow-incomplete-defs"
"--disallow-untyped-decorators"
true
];
};
# TODO Could add some, could also remove some
};
};
xdg.configFile = {
"pythonstartup.py" = {
text = (builtins.readFile ./pythonstartup.py);
};
};
};
}

View file

@ -34,9 +34,12 @@
# TODO Convert existing LaTeX documents into using Nix build system
# texlive is big and not that much used, sooo
pdftk
# Misc
haskellPackages.dice
hunspell
hunspellDicts.en_GB-ize
hunspellDicts.en_US
hunspellDicts.fr-moderne
hunspellDicts.nl_NL
# TODO libreoffice-extension-languagetool or libreoffice-extension-grammalecte-fr
] ++ lib.optionals config.frogeye.desktop.xorg [

View file

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View file

@ -1,4 +1,4 @@
{ pkgs ? import <nixpkgs> { config = { }; overlays = [ ]; }, lib, config, ... }:
{ pkgs ? import <nixpkgs> { config = { }; overlays = [ ]; }, ... }:
# Tried using pyproject.nix but mpd2 dependency wouldn't resolve,
# is called pyton-mpd2 on PyPi but mpd2 in nixpkgs.
let
@ -22,7 +22,7 @@ let
};
in
{
config = lib.mkIf config.frogeye.desktop.xorg {
config = {
xsession.windowManager.i3.config.bars = [ ];
programs.autorandr.hooks.postswitch = {
frobar = "${pkgs.systemd}/bin/systemctl --user restart frobar";

View file

@ -8,9 +8,9 @@ def run():
Bar.init()
Updater.init()
WORKSPACE_THEME = 8
FOCUS_THEME = 2
URGENT_THEME = 0
WORKSPACE_THEME = 0
FOCUS_THEME = 3
URGENT_THEME = 1
CUSTOM_SUFFIXES = "▲■"
customNames = dict()
@ -30,22 +30,22 @@ def run():
)
# TODO Middle
Bar.addSectionAll(MpdProvider(theme=9), BarGroupType.LEFT)
Bar.addSectionAll(MpdProvider(theme=7), BarGroupType.LEFT)
# Bar.addSectionAll(I3WindowTitleProvider(), BarGroupType.LEFT)
# TODO Computer modes
SYSTEM_THEME = 3
DANGER_THEME = 1
CRITICAL_THEME = 0
SYSTEM_THEME = 2
DANGER_THEME = FOCUS_THEME
CRITICAL_THEME = URGENT_THEME
Bar.addSectionAll(CpuProvider(), BarGroupType.RIGHT)
Bar.addSectionAll(RamProvider(), BarGroupType.RIGHT)
Bar.addSectionAll(TemperatureProvider(), BarGroupType.RIGHT)
Bar.addSectionAll(BatteryProvider(), BarGroupType.RIGHT)
# Peripherals
PERIPHERAL_THEME = 6
NETWORK_THEME = 5
PERIPHERAL_THEME = 5
NETWORK_THEME = 4
# TODO Disk space provider
# TODO Screen (connected, autorandr configuration, bbswitch) provider
Bar.addSectionAll(PulseaudioProvider(theme=PERIPHERAL_THEME), BarGroupType.RIGHT)
@ -53,12 +53,12 @@ def run():
Bar.addSectionAll(NetworkProvider(theme=NETWORK_THEME), BarGroupType.RIGHT)
# Personal
PERSONAL_THEME = 7
PERSONAL_THEME = 0
# Bar.addSectionAll(KeystoreProvider(theme=PERSONAL_THEME), BarGroupType.RIGHT)
# Bar.addSectionAll(NotmuchUnreadProvider(dir='~/.mail/', theme=PERSONAL_THEME), BarGroupType.RIGHT)
# Bar.addSectionAll(TodoProvider(dir='~/.vdirsyncer/currentCalendars/', theme=PERSONAL_THEME), BarGroupType.RIGHT)
TIME_THEME = 4
TIME_THEME = 6
Bar.addSectionAll(TimeProvider(theme=TIME_THEME), BarGroupType.RIGHT)
# Bar.run()

View file

@ -313,26 +313,29 @@ class SectionThread(threading.Thread):
class Section:
# TODO Update all of that to base16
# COLORS = ['#272822', '#383830', '#49483e', '#75715e', '#a59f85', '#f8f8f2',
# '#f5f4f1', '#f9f8f5', '#f92672', '#fd971f', '#f4bf75', '#a6e22e',
# '#a1efe4', '#66d9ef', '#ae81ff', '#cc6633']
COLORS = [
"#092c0e",
"#143718",
"#5a7058",
"#677d64",
"#89947f",
"#99a08d",
"#fae2e3",
"#fff0f1",
"#e0332e",
"#cf4b15",
"#bb8801",
"#8d9800",
"#1fa198",
"#008dd1",
"#5c73c4",
"#d43982",
"#181818",
"#AB4642",
"#A1B56C",
"#F7CA88",
"#7CAFC2",
"#BA8BAF",
"#86C1B9",
"#D8D8D8",
"#585858",
"#AB4642",
"#A1B56C",
"#F7CA88",
"#7CAFC2",
"#BA8BAF",
"#86C1B9",
"#F8F8F8",
]
FGCOLOR = "#fff0f1"
BGCOLOR = "#092c0e"
FGCOLOR = "#F8F8F2"
BGCOLOR = "#272822"
THEMES = list()
EMPTY = (FGCOLOR, BGCOLOR)
@ -350,8 +353,6 @@ class Section:
def init():
for t in range(8, 16):
Section.THEMES.append((Section.COLORS[0], Section.COLORS[t]))
Section.THEMES.append((Section.COLORS[0], Section.COLORS[3]))
Section.THEMES.append((Section.COLORS[0], Section.COLORS[6]))
Section.updateThread.start()

View file

@ -66,7 +66,7 @@ class AlertLevel(enum.Enum):
class AlertingSection(StatefulSection):
# TODO EASE Correct settings for themes
THEMES = {AlertLevel.NORMAL: 3, AlertLevel.WARNING: 1, AlertLevel.DANGER: 0}
THEMES = {AlertLevel.NORMAL: 2, AlertLevel.WARNING: 3, AlertLevel.DANGER: 1}
PERSISTENT = True
def getLevel(self, quantity):

View file

@ -3,28 +3,13 @@
config = lib.mkIf config.frogeye.gaming {
# Using config.nixpkgs.<something> creates an infinite recursion,
# but the above might not be correct in case of cross-compiling?
home = {
packages = with pkgs; [
# gaming
dolphin-emu
yuzu-mainline
minecraft
# TODO factorio
home.packages = with pkgs; [
# gaming
yuzu-mainline
minecraft
# TODO factorio
steam # Common pitfall: https://github.com/NixOS/nixpkgs/issues/86506#issuecomment-623746883
itch
(pkgs.python3Packages.ds4drv.overrideAttrs (old: {
src = fetchFromGitHub {
owner = "TheDrHax";
repo = "ds4drv-cemuhook";
rev = "a58f63b70f8d8efa33e5e82a8888a1e08754aeed";
sha256 = "sha256-oMvHw5zeO0skoiqLU+EdjUabTvkipeBh+m8RHJcWZP8=";
};
}))
];
sessionVariables = {
BOOT9_PATH = "${config.xdg.dataHome}/citra-emu/sysdata/boot9.bin";
};
};
steam # Common pitfall: https://github.com/NixOS/nixpkgs/issues/86506#issuecomment-623746883
];
};
}

View file

@ -1,83 +0,0 @@
{ pkgs, lib, config, ... }:
{
config = lib.mkIf config.programs.git.enable {
home.packages = [
(pkgs.writeShellApplication {
name = "git-sync";
text = (lib.strings.concatLines
(map
(r: ''
echo "===== ${r.path}"
if [ ! -d "${r.path}" ]
then
${pkgs.git}/bin/git clone "${r.uri}" "${r.path}"
else
(
cd "${r.path}"
${pkgs.git}/bin/git --no-optional-locks diff --quiet || echo "Repository is dirty!"
${pkgs.git}/bin/git pull || true
# Only push if there's something to push. Also prevents from trying to push on repos where we don't have rights.
(${pkgs.git}/bin/git --no-optional-locks status --porcelain -b --ignore-submodules | grep ' \[ahead [0-9]\+\]' && ${pkgs.git}/bin/git push) || true
)
fi
'')
(lib.attrsets.attrValues config.services.git-sync.repositories)
)
);
})
];
programs.git = {
package = pkgs.gitFull;
aliases = {
"git" = "!exec git"; # In case I write one too many git
};
ignores = [
"*.swp"
"*.swo"
"*.ycm_extra_conf.py"
"tags"
".mypy_cache"
];
delta = {
enable = true;
options = {
line-numbers = true;
syntax-theme = "base16";
};
};
# Also tried difftastic, and while I like the default theme it's a bit
# less configurable
lfs.enable = true;
userEmail = lib.mkDefault "geoffrey@frogeye.fr";
userName = lib.mkDefault "Geoffrey Frogeye";
extraConfig = {
core = {
editor = "nvim";
};
push = {
default = "matching";
};
pull = {
ff = "only";
};
} // lib.optionalAttrs config.frogeye.desktop.xorg {
diff.tool = "meld";
difftool.prompt = false;
"difftool \"meld\"".cmd = "${pkgs.meld}/bin/meld \"$LOCAL\" \"$REMOTE\"";
# This escapes quotes, which isn't the case in the original, hoping this isn't an issue.
};
};
services = {
git-sync = {
enable = false; # The real thing syncs too quickly and asks for passphrase, which is annoying
# So for now it's just a way to park config which will be reused by git-sync-* commands
repositories = {
dotfiles = {
path = "${config.xdg.configHome}/dotfiles";
uri = lib.mkDefault "https://git.frogeye.fr/geoffrey/dotfiles.git";
};
};
};
};
};
}

View file

@ -1,50 +0,0 @@
{ pkgs, lib, config, ... }:
{
config = lib.mkIf config.programs.gpg.enable {
frogeye.hooks.lock = ''
echo RELOADAGENT | ${pkgs.gnupg}/bin/gpg-connect-agent
'';
programs.gpg = {
homedir = "${config.xdg.stateHome}/gnupg";
settings = {
# Remove fluff
no-greeting = true;
no-emit-version = true;
no-comments = true;
# Output format that I prefer
keyid-format = "0xlong";
# Show fingerprints
with-fingerprint = true;
# Make sure to show if key is invalid
# (should be default on most platform,
# but just to be sure)
list-options = "show-uid-validity";
verify-options = "show-uid-validity";
# Stronger algorithm (https://wiki.archlinux.org/title/GnuPG#Different_algorithm)
personal-digest-preferences = "SHA512";
cert-digest-algo = "SHA512";
default-preference-list = "SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed";
personal-cipher-preferences = "TWOFISH CAMELLIA256 AES 3DES";
};
publicKeys = [{
source = builtins.fetchurl {
url = "https://keys.openpgp.org/vks/v1/by-fingerprint/4FBA930D314A03215E2CDB0A8312C8CAC1BAC289";
sha256 = "sha256:10y9xqcy1vyk2p8baay14p3vwdnlwynk0fvfbika65hz2z8yw2cm";
};
trust = "ultimate";
}];
};
services.gpg-agent = rec {
enableBashIntegration = true;
enableZshIntegration = true;
pinentryFlavor = "gnome3";
# gnome3 is nicer, but requires gcr as a dbus package.
# Which is in my NixOS config, and on non-NixOS too.
# It will fall back to ncurses when running in non-graphics mode.
defaultCacheTtl = 3600;
defaultCacheTtlSsh = defaultCacheTtl;
maxCacheTtl = 3*3600;
maxCacheTtlSsh = maxCacheTtl;
};
};
}

View file

@ -1,61 +0,0 @@
{ lib, config, ... }:
{
config = {
frogeye = {
# TODO Move to relevant config file. Rest can probably removed.
direnv = {
CARGOHOME = "${config.xdg.cacheHome}/cargo"; # There are config in there that we can version if one want
DASHT_DOCSETS_DIR = "${config.xdg.cacheHome}/dash_docsets";
GRADLE_USER_HOME = "${config.xdg.cacheHome}/gradle";
MIX_ARCHIVES = "${config.xdg.cacheHome}/mix/archives";
MONO_GAC_PREFIX = "${config.xdg.cacheHome}/mono";
PARALLEL_HOME = "${config.xdg.cacheHome}/parallel";
TERMINFO = "${config.xdg.configHome}/terminfo";
WINEPREFIX = "${config.xdg.stateHome}/wineprefix/default";
};
junkhome = [
"adb"
"audacity"
"cabal" # TODO May have options but last time I tried it it crashed
"itch"
"simplescreenrecorder" # Easy fix https://github.com/MaartenBaert/ssr/blob/1556ae456e833992fb6d39d40f7c7d7c337a4160/src/Main.cpp#L252
"vd"
"wpa_cli"
# TODO Maybe we can do something about node-gyp
];
};
home = {
activation.createDirenvFolders = lib.hm.dag.entryAfter [ "writeBoundary" ]
(lib.strings.concatLines (map (d: "mkdir -p ${d}") (
(builtins.attrValues config.frogeye.direnv) ++ [ "${config.xdg.cacheHome}/junkhome" ]
)));
sessionVariables = config.frogeye.direnv;
};
programs.bash.shellAliases = lib.attrsets.mergeAttrsList (map (p: { "${p}" = "HOME=${config.xdg.cacheHome}/junkhome ${p}"; }) config.frogeye.junkhome);
};
options.frogeye = {
direnv = lib.mkOption {
default = { };
example = lib.literalExpression ''
{
DASHT_DOCSETS_DIR = "''${config.xdg.cacheHome}/dash_docsets";
}
'';
description = ''
Environment variables for which the value is a folder that will be automatically created.
Useful for keeping programs data out of $HOME for programs that won't create the directory themselves.
'';
type = lib.types.attrsOf lib.types.str;
};
junkhome = lib.mkOption {
default = [ ];
description = ''
Program names that will be run with a different HOME so they don't clutter the real one.
Useful for programs that don't follow the XDG specification and tend to advertise themselves.
'';
type = lib.types.listOf lib.types.str;
};
# TODO Should make a nix package wrapper instead, so it also works from dmenu
};
}

View file

@ -1,35 +0,0 @@
{ pkgs, lib, config, ... }:
{
config = {
home.packages = with pkgs; [
htop
iftop
iotop
lsof
progress
pv
speedtest-cli
strace
];
programs.bash.shellAliases = {
iftop = "iftop -c ${config.xdg.configHome}/iftoprc";
tracefiles = ''${pkgs.strace}/bin/strace -f -t -e trace=file'';
};
xdg = {
configFile = {
"iftoprc" = {
text = ''
port-resolution: no
promiscuous: no
port-display: on
link-local: yes
use-bytes: yes
show-totals: yes
log-scale: yes
'';
};
};
};
};
}

View file

@ -1,24 +0,0 @@
{ pkgs, lib, config, ... }:
{
config = {
home.packages = with pkgs; [
nvd
nix-diff
nix-tree
nix-output-monitor
];
programs.nix-index = {
# For non-NixOS systems
enable = false; # TODO Index is impossible to generate, should use https://github.com/nix-community/nix-index-database
# but got no luck without flakes
enableZshIntegration = true;
};
nix = {
package = lib.mkDefault pkgs.nixFlakes;
settings = {
experimental-features = [ "nix-command" "flakes" ];
warn-dirty = false;
};
};
};
}

View file

@ -1,19 +0,0 @@
{ pkgs, lib, config, ... }:
{
config = {
home = {
sessionVariables = {
PAGER = "less";
LESSHISTFILE = "${config.xdg.stateHome}/lesshst";
LESS = "-R";
LESS_TERMCAP_mb = "$(echo $'\\E[1;31m')"; # begin blink
LESS_TERMCAP_md = "$(echo $'\\E[1;36m')"; # begin bold
LESS_TERMCAP_me = "$(echo $'\\E[0m')"; # reset bold/blink
LESS_TERMCAP_se = "$(echo $'\\E[0m')"; # reset reverse video
LESS_TERMCAP_so = "$(echo $'\\E[01;44;33m')"; # begin reverse video
LESS_TERMCAP_ue = "$(echo $'\\E[0m')"; # reset underline
LESS_TERMCAP_us = "$(echo $'\\E[1;32m')"; # begin underline
};
};
};
}

View file

@ -1,112 +0,0 @@
{ pkgs, lib, config, ... }:
let
mod = config.xsession.windowManager.i3.config.modifier;
in
{
config = {
home.packages = with pkgs; [
pwgen
(pkgs.writeShellApplication {
name = "install-passwords";
runtimeInputs = [ yq gawk moreutils ];
text = (lib.strings.concatLines (map
(file: ''
(
echo "===== Preparing to write ${file.path}"
temp="$(mktemp --tmpdir="${builtins.dirOf file.path}")"
cat "${file.template}" > "$temp"
'' + (lib.strings.concatLines (map
(password: (if password.selector == null then ''
echo "Reading ${password.path} for substituting ${password.variable}"
value="$(pass "${password.path}" | head -n1)"
'' else ''
echo "Reading ${password.path} -> ${password.selector} for substituting ${password.variable}"
value="$(pass "${password.path}" | tail -n +2 | yq -r '.${password.selector}')"
'') + ''
key="${password.variable}"
K="$key" V="$value" awk '{ gsub (ENVIRON["K"], ENVIRON["V"]); print }' "$temp" | sponge "$temp"
'')
(lib.attrsets.attrValues file.passwords))) + ''
echo "Moving the file in place"
chown "${file.owner}" "$temp"
chmod u=r "$temp"
mv -f "$temp" "${file.path}"
)
'')
config.frogeye.passwordFiles)
);
})
];
programs = {
bash.shellAliases = {
pw = ''${pkgs.pwgen}/bin/pwgen 32 -y''; # Generate passwords. ln((26*2+10)**32)/ln(2) ≅ 190 bits of entropy
};
password-store.enable = true;
};
xsession.windowManager.i3.config.keybindings."${mod}+c" = "exec --no-startup-id ${config.programs.rofi.pass.package}/bin/rofi-pass --last-used";
# TODO Try autopass.cr
};
options = {
frogeye.passwordFiles =
let
defaultvar = "@PASSWORD@";
pwtype = { name, ... }: {
options = {
variable = lib.mkOption {
type = lib.types.str;
default = name;
description = "String in the template that will be substituted by the actual password";
};
path = lib.mkOption {
type = lib.types.str;
description = "Path to the password store entry";
};
selector = lib.mkOption {
type = lib.types.str;
default = null;
description = "If set, will parse the password metadata as YML and use selector (yq) instead of the password.";
};
};
};
mainConfig = config;
in
lib.mkOption {
default = [ ];
type = lib.types.listOf (lib.types.submodule ({ config, ... }: {
options = {
path = lib.mkOption {
type = lib.types.str;
description = "Where to place the file.";
};
owner = lib.mkOption {
type = lib.types.str;
default = mainConfig.home.username;
description = "Who will own the file.";
};
template = lib.mkOption {
type = lib.types.path;
default = pkgs.writeTextFile {
name = "pwfile-template";
text = config.text;
};
description = "Path to the template used to make the file. Exclusive with `text`.";
};
text = lib.mkOption {
type = lib.types.str;
default = defaultvar;
description = "Content of the template used to make the file. Exclusive with `template`.";
};
passwords = lib.mkOption {
default = lib.optionalAttrs (config.password != null) { ${defaultvar} = config.password; };
type = lib.types.attrsOf (lib.types.submodule pwtype);
description = "Paths to passwords that will substitute the variables in the template. Exclusive with `password`";
};
password = lib.mkOption {
type = lib.types.submodule ({ ... }@args: pwtype (args // { name = defaultvar; }));
description = "Path to password that will substitute '@PASSWORD@' in the template. Exclusive with `passwords`.";
};
};
}));
};
};
}

View file

@ -1,21 +0,0 @@
{ pkgs, lib, config, ... }:
{
config = lib.mkIf config.programs.less.enable {
programs.powerline-go = {
enable = true;
modules = [ "user" "host" "venv" "cwd" "perms" "git" ];
modulesRight = [ "jobs" "exit" "duration" "load" ];
settings = {
colorize-hostname = true;
max-width = 25;
cwd-max-dir-size = 10;
duration = "$( test -n \"$__TIMER\" && echo $(( $EPOCHREALTIME - $\{__TIMER:-EPOCHREALTIME})) || echo 0 )";
# UPST Implement this properly in home-manager, would allow for bash support
};
extraUpdatePS1 = ''
unset __TIMER
echo -en "\033]0; $USER@$HOST $PWD\007"
'';
};
};
}

View file

@ -1,45 +0,0 @@
{ pkgs, config, ... }:
let
ulf = pkgs.writers.writePython3 "update-local-flakes" {
} (builtins.readFile ./update-local-flakes.py);
in
{
home.packages = [
(pkgs.writeShellApplication {
name = "rb";
text = ''
verb="switch"
if [ "$#" -ge 1 ]
then
verb="$1"
shift
fi
nixos_flake="/etc/nixos/flake.nix"
if [ -f "$nixos_flake" ]
then
sudo ${ulf} "$nixos_flake"
# ${pkgs.nix-output-monitor}/bin/nom build "$(dirname "$nixos_flake")#nixosConfigurations.$HOSTNAME.config.system.build.toplevel"
if [ "$verb" = "switch" ] || [ "$verb" = "test" ]
then
sudo nixos-rebuild "$verb" --specialisation ${config.frogeye.polarity} "$@"
else
sudo nixos-rebuild "$verb" "$@"
fi
fi
hm_flake="${config.xdg.configHome}/home-manager/flake.nix"
if [ -f "$hm_flake" ]
then
${ulf} "$hm_flake"
home-manager "$verb" "$@"
fi
nod_flake="${config.xdg.configHome}/nix-on-droid/flake.nix"
if [ -f "$nod_flake" ]
then
${ulf} "$nod_flake"
nix-on-droid "$verb" --flake "$(dirname "$nod_flake")" "$@"
fi
'';
})
];
}
# TODO make it a flake application, optional nom (is slow), test then boot, flags to confirm each, nvd diff here

View file

@ -1,64 +0,0 @@
import argparse
import json
import os
import subprocess
GET_INPUTS_CMD = [
"nix-instantiate",
"--eval",
"--json", # This parser is stupid, better provide it with pre-eaten stuff
"--expr",
"builtins.fromJSON (builtins.toJSON (import ./flake.nix).inputs)",
]
def process_flake(flake: str) -> None:
# get full path
if not os.path.isfile(flake):
raise FileNotFoundError(f"Flake not found: {flake}")
dir = os.path.dirname(flake)
# import dependencies
p = subprocess.run(GET_INPUTS_CMD, cwd=dir, stdout=subprocess.PIPE)
deps = json.loads(p.stdout)
p.check_returncode()
# for each dependency
for dep_name, dep in deps.items():
dep_url = dep["url"]
# if not local path, continue
if not (
dep_url.startswith("path:")
or dep_url.startswith("git+file:")
):
continue
if dep.get("flake", True):
# get flake file corresponding
dep_path = dep_url.split(":")[1]
if not dep_path.startswith("/"):
dep_path = os.path.join(dir, dep_path)
dep_path = os.path.normpath(dep_path)
dep_flake = os.path.join(dep_path, "flake.nix")
# call this function with the flake file
process_flake(dep_flake)
# update lockfile
cmd = [
"nix",
"--extra-experimental-features",
"nix-command",
"--extra-experimental-features",
"flakes",
"flake",
"update",
dep_name,
]
p = subprocess.run(cmd, cwd=dir)
p.check_returncode()
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Recursively update lockfiles "
"of flakes located on the system"
)
parser.add_argument("flake", help="Starting flake", default="flake.nix")
args = parser.parse_args()
process_flake(args.flake)

View file

@ -1,8 +1,8 @@
#!/usr/bin/env nix-shell
#! nix-shell -i bash --pure
#! nix-shell -p bash jq curl cacert findutils coreutils
#! nix-shell -p bash jq curl findutils coreutils
set -euxo pipefail
set -euo pipefail
url="https://ip.frogeye.fr/json"
cachedir="$HOME/.cache/lip"
@ -16,6 +16,7 @@ then
jq_sel="$@"
fi
if [ -n "$ip" ]
then
cachefile="$cachedir/$ip"

View file

@ -158,7 +158,8 @@ do
echo Processing $music
temp=$(mktemp --suffix .flac)
ffmpeg -y -i "$music" -compression_level 8 "$temp"
cp "$music" "$temp"
ffmpeg -8 -o "$temp"
echo "→ Optimize done"
replace "$temp" "$music"

View file

@ -1,9 +1,8 @@
#!/usr/bin/env nix-shell
#! nix-shell -i python3 --pure
#! nix-shell -p python3 python3Packages.coloredlogs r128gain
#! nix-shell -p python3 python3Packages.coloredlogs python3Packages.r128gain
# TODO r128gain is not maintainted anymore
# 24.05 rsgain replaces it, does the same job as I do with albums
# Normalisation is done at the default of each program,
# which is usually -89.0 dB

View file

@ -1,6 +1,6 @@
#!/usr/bin/env nix-shell
#! nix-shell -i python3 --pure
#! nix-shell -p python3 python3Packages.coloredlogs python3Packages.progressbar2 ffmpeg
#! nix-shell -p python3 python3Packages.coloredlogs python3Packages.progresbar2 ffmpeg
# pylint: disable=C0103
import logging

View file

@ -1,38 +0,0 @@
{ pkgs, lib, config, ... }:
let
cfg = config.programs.bash;
in
{
config = {
programs = {
bash = {
enable = true;
bashrcExtra = ''
shopt -s expand_aliases
shopt -s histappend
'';
historySize = 100000;
historyFile = "${config.xdg.stateHome}/shell_history";
historyFileSize = 100000;
# TODO Check out Atuin
historyControl = [ "erasedups" "ignoredups" "ignorespace" ];
};
zsh = {
enable = true;
enableAutosuggestions = true;
enableCompletion = true;
syntaxHighlighting.enable = true;
historySubstringSearch.enable = true;
initExtra = builtins.readFile ./zshrc.sh;
defaultKeymap = "viins";
history = {
size = cfg.historySize;
save = cfg.historyFileSize;
path = cfg.historyFile;
expireDuplicatesFirst = true;
};
shellAliases = cfg.shellAliases;
};
};
};
}

View file

@ -1,9 +1,6 @@
{ pkgs, lib, config, ... }:
{ ... }:
{
config = {
frogeye.hooks.lock = ''
${pkgs.openssh}/bin/ssh-add -D
'';
programs.ssh = {
enable = true;
controlMaster = "auto";

73
hm/style.nix Normal file
View file

@ -0,0 +1,73 @@
{ pkgs, config, lib, ... }:
let
# Currently last commit in https://github.com/danth/stylix/pull/194
stylix = builtins.fetchTarball "https://github.com/willemml/stylix/archive/2ed2b0086b41d582aca26e083c19c0e47c8991e3.tar.gz";
polarityFile = "${config.xdg.stateHome}/theme_polarity";
polarityFromFile = if builtins.pathExists polarityFile then lib.strings.fileContents polarityFile else "light";
polarity = if config.frogeye.polarity == "dynamic" then polarityFromFile else config.frogeye.polarity;
phases = [
{ command = "jour"; polarity = "light"; }
{ command = "crepuscule"; polarity = "dark"; }
{ command = "nuit"; polarity = "dark"; }
];
cfg = config.frogeye.desktop.phasesBrightness;
bg = builtins.fetchurl {
url = "https://get.wallhere.com/photo/sunlight-abstract-minimalism-green-simple-circle-light-leaf-wave-material-line-wing-computer-wallpaper-font-close-up-macro-photography-124350.png";
sha256 = "sha256:1zfq3f3v34i45mi72pkfqphm8kbhczsg260xjfl6dbydy91d7y93";
};
bg_nored = pkgs.runCommand "bg.png" { env.GIMP2_DIRECTORY = "/tmp"; } ''
${pkgs.gimp}/bin/gimp ${bg} --no-interface --no-data --no-fonts bg.png -b "(gimp-levels 2 1 0 255 1 0 0)" -b "(file-png-save-defaults 1 1 2 '$out' '$out')" -b "(gimp-quit 1)"
'';
in
{
imports = [ (import stylix).homeManagerModules.stylix ];
stylix = {
base16Scheme = "${pkgs.base16-schemes}/share/themes/solarized-${polarity}.yaml";
image = bg_nored; # The background is set on some occasions, autorandr + feh do the rest
fonts = {
monospace = {
package = pkgs.nerdfonts.override {
fonts = [ "DejaVuSansMono" ]; # Choose from https://github.com/NixOS/nixpkgs/blob/6ba3207643fd27ffa25a172911e3d6825814d155/pkgs/data/fonts/nerdfonts/shas.nix
};
name = "DejaVuSansM Nerd Font";
};
};
targets = {
i3.enable = false; # I prefer my own styles
tmux.enable = false; # Using another theme
};
};
# Setting a custom base16 theme via nixvim:
# - Is required so nixvim works
# - For the rest only works on dark polarity, use the colorscheme otherwise... shrug
programs.nixvim.colorschemes.base16.colorscheme = "solarized-${polarity}";
# Fix https://nix-community.github.io/home-manager/index.html#_why_do_i_get_an_error_message_about_literal_ca_desrt_dconf_literal_or_literal_dconf_service_literal
# home.packages = [ pkgs.dconf ];
dconf.enable = false; # Otherwise standalone home-manager complains it can't find /etc/dbus-1/session.conf on Arch.
# Symlinking it to /usr/share/dbus-1/session.conf goes further but not much.
home.packages = map
(phase: (pkgs.writeShellApplication {
name = "${phase.command}";
runtimeInputs = [ pkgs.brightnessctl ];
text = (lib.optionalString cfg.enable ''
brightnessctl set ${builtins.getAttr phase.command cfg}
'') + ''
echo ${phase.polarity} > ${polarityFile}
if command -v home-manager
then
home-manager switch
else
# In two steps to get the visual changes slightly earlier
sudo /nix/var/nix/profiles/system/specialisation/${phase.polarity}/bin/switch-to-configuration test
sudo /nix/var/nix/profiles/system/specialisation/${phase.polarity}/bin/switch-to-configuration boot
fi
'';
})
)
phases;
}

View file

@ -1,16 +0,0 @@
{ pkgs, config, lib, ... }:
{
config = {
stylix = {
polarity = config.frogeye.polarity;
fonts = {
monospace = {
package = pkgs.nerdfonts.override {
fonts = [ "DejaVuSansMono" ]; # Choose from https://github.com/NixOS/nixpkgs/blob/6ba3207643fd27ffa25a172911e3d6825814d155/pkgs/data/fonts/nerdfonts/shas.nix
};
name = "DejaVuSansM Nerd Font";
};
};
};
};
}

View file

@ -1,34 +0,0 @@
{ pkgs, lib, config, ... }:
let
themepack = pkgs.tmuxPlugins.mkTmuxPlugin
rec {
pluginName = "tmux-themepack";
version = "1.1.0";
rtpFilePath = "themepack.tmux";
src = pkgs.fetchFromGitHub {
owner = "jimeh";
repo = "tmux-themepack";
rev = "${version}";
sha256 = "f6y92kYsKDFanNx5ATx4BkaB/E7UrmyIHU/5Z01otQE=";
};
};
in
{
config = lib.mkIf config.programs.tmux.enable {
home = {
packages = [ pkgs.screen ];
sessionVariables.SCREENRC = "${config.xdg.configHome}/screenrc";
};
programs.tmux = {
mouse = false;
clock24 = true;
# TODO Vim mode?
plugins = with pkgs.tmuxPlugins; [
sensible
];
extraConfig = builtins.readFile ./tmux.conf + "source-file ${themepack}/share/tmux-plugins/tmux-themepack/powerline/default/green.tmuxtheme\n";
};
stylix.targets.tmux.enable = false;
xdg.configFile.screenrc.text = (builtins.readFile ./screenrc);
};
}

51
hm/usernix/default.nix Normal file
View file

@ -0,0 +1,51 @@
{ pkgs, lib, config, ... }:
let
ensureNixPath = "${config.xdg.configHome}/dotfiles/ensure_nix.sh";
in
{
config = lib.mkIf config.frogeye.userNix {
home.activation = {
# When Nix is installed in the user directory via a proot, systemd --user
# is started outside of it, so it cannot access /nix. So we need to:
# - Ensure files systemd access aren't via /nix.
# Sometimes there's multiple layers of redirection, so easiest way is
# to copy the file outside the repository, but if using regular files
# directly home-manager will complain that it will overwrite
# something it didn't write.
# - Wrap services entrypoints into a proot wrapper
prootSystemd = lib.hm.dag.entryAfter [ "linkGeneration" ] [ "reloadSystemd" ] ''
cd ${config.xdg.configHome}/systemd/user
${pkgs.findutils}/bin/find . -type l | while read path
do
${pkgs.gnused}/bin/sed 's|^Exec\S\+=|\0${ensureNixPath} |' "$path" > "''${path}-proot"
rm "$path"
ln -s "''${path}-proot" "$path"
done
'';
# I wonder if it's possible to do this in a slightly more Nix way, without causing infinite recursion
# Create a graphical entrypoint by overriding one of the OS programs
graphicalEntrypoints =
let
graphicalEntrypoint = pkgs.writeTextFile {
name = "graphical-entrypoint";
text = ''
#!/usr/bin/env sh
exec ${ensureNixPath} ${config.xsession.scriptPath}
'';
executable = true;
};
in
lib.mkIf config.frogeye.desktop.xorg
lib.hm.dag.entryAfter [ "writeBoundary" ] ''
cp -f ${graphicalEntrypoint} ${config.home.homeDirectory}/.local/bin/cinnamon-session-cinnamon
'';
};
# Some systemd options don't work if you're running a proot inside, so they need to be relaxed
# TODO Following is what's necessary to remove for Syncthing to work. Might be applicable on all services.
# PrivateUsers=true
# RestrictNamespaces=true
# SystemCallFilter=@system-service
};
}

403
hm/vim.nix Normal file
View file

@ -0,0 +1,403 @@
{ pkgs, lib, config, ... }:
let
nixvim = import (builtins.fetchGit {
url = "https://github.com/nix-community/nixvim";
rev = "c96d7b46d05a78e695ed1c725d1596b65509b4f9"; # 24.05 Anythin after this commit works
});
vim-shot-f = pkgs.vimUtils.buildVimPlugin {
pname = "vim-shot-f";
version = "2016-02-05";
src = pkgs.fetchFromGitHub {
owner = "deris";
repo = "vim-shot-f";
rev = "eea71d2a1038aa87fe175de9150b39dc155e5e7f";
sha256 = "iAPvIs/lhW+w5kFTZKaY97D/kfCGtqKrJVFvZ8cHu+c=";
};
meta.homepage = "https://github.com/deris/vim-shot-f";
};
quick-scope = pkgs.vimUtils.buildVimPlugin rec {
pname = "quick-scope";
version = "2.6.1";
src = pkgs.fetchFromGitHub {
owner = "unblevable";
repo = "quick-scope";
rev = "v${version}";
sha256 = "TcA4jZIdnQd06V+JrXGiCMr0Yhm9gB6OMiTSdzMt/Qw=";
};
meta.homepage = "https://github.com/unblevable/quick-scope";
};
in
{
imports = [
nixvim.homeManagerModules.nixvim
];
programs.nixvim = {
enable = true;
options = {
# From https://www.hillelwayne.com/post/intermediate-vim/
title = true;
number = true;
relativenumber = true;
scrolloff = 10;
lazyredraw = true; # Do not redraw screen in the middle of a macro. Makes them complete faster.
cursorcolumn = true;
ignorecase = true;
smartcase = true;
gdefault = true;
tabstop = 4;
shiftwidth = 4;
expandtab = true;
splitbelow = true;
visualbell = true;
updatetime = 250;
undofile = true;
# From http://stackoverflow.com/a/5004785/2766106
list = true;
listchars = "tab:,trail:·,extends:,precedes:,nbsp:_";
showbreak = "";
wildmode = "longest:full,full";
wildmenu = true;
};
globals = {
netrw_fastbrowse = 0; # Close the file explorer once you select a file
};
plugins = {
# Catches attention when cursor changed position
# TODO Unmapped, do I still want to use it?
specs = {
enable = true;
min_jump = 5;
fader = { builtin = "pulse_fader"; };
resizer = { builtin = "shrink_resizer"; };
};
# Tabline
barbar.enable = true;
# Go to whatever
telescope = {
enable = true;
keymaps = {
gF = "find_files";
gf = "git_files";
gB = "buffers";
gl = "current_buffer_fuzzy_find";
gL = "live_grep";
gT = "tags";
gt = "treesitter";
gm = "marks";
gh = "oldfiles";
gH = "command_history";
gS = "search_history";
gC = "commands";
gr = "lsp_references";
ge = "diagnostics";
# ga = "lsp_code_actions";
# gE = "lsp_workspace_diagnostics";
# TODO Above makes nvim crash on startup, action is not provided
gd = "lsp_definitions";
gs = "lsp_document_symbols";
};
defaults = {
vimgrep_arguments = [
"${pkgs.ripgrep}/bin/rg"
"--color=never"
"--no-heading"
"--with-filename"
"--line-number"
"--column"
"--smart-case"
];
};
extensions.fzf-native = {
enable = true;
caseMode = "smart_case";
fuzzy = true;
overrideFileSorter = true;
overrideGenericSorter = true;
};
};
# Surrounding pairs
surround.enable = true; # Change surrounding pairs (e.g. brackets, quotes)
# Language Server
lsp = {
enable = true;
keymaps = {
silent = true;
diagnostic = {
"<Space>e" = "open_float";
"[e" = "goto_prev";
"]e" = "goto_next";
};
lspBuf = {
"gD" = "declaration";
"K" = "hover";
"gi" = "implementation";
"<C-S-k>" = "signature_help";
"<space>wa" = "add_workspace_folder";
"<space>wr" = "remove_workspace_folder";
# "<space>wl" = "list_workspace_folder";
# TODO Full thing was function() print(vim.inspect(vim.lsp.buf.list_workspace_folder())) end but not sure I'm ever really using this
# Also makes nvim crash like this, so uncommented
"<space>D" = "type_definition";
"<space>rn" = "rename";
"<space>f" = "format";
# TODO Full thing was function() vim.lsp.buf.format { async = true } end, so async while this isn't
# Maybe replace this with lsp-format?
};
};
servers = {
ansiblels.enable = config.frogeye.dev.ansible; # Ansible
bashls.enable = true; # Bash
jsonls.enable = true; # JSON
lua-ls.enable = true; # Lua (for Neovim debugging)
perlpls.enable = config.frogeye.dev.perl; # Perl
pylsp = {
# Python
enable = config.frogeye.dev.python;
settings.plugins = {
black.enabled = true;
flake8 = {
enabled = true;
maxLineLength = 88; # Compatibility with Black
};
isort.enabled = true;
mccabe.enabled = true;
pycodestyle = {
enabled = true;
maxLineLength = 88; # Compatibility with Black
};
pyflakes.enabled = true;
pylint.enabled = true;
pylsp_mypy = {
enabled = true;
overrides = [
"--cache-dir=${config.xdg.cacheHome}/mypy"
"--ignore-missing-imports"
"--disallow-untyped-defs"
"--disallow-untyped-calls"
"--disallow-incomplete-defs"
"--disallow-untyped-decorators"
true
];
};
# TODO Could add some, could also remove some
};
};
phpactor.enable = config.frogeye.dev.php; # PHP
rnix-lsp.enable = true; # Nix
# TODO Something for SQL. sqls is deprecated, sqlls is not in Nixpkgs. Probably needs a DB connection configured anyways?
yamlls.enable = true; # YAML
# TODO Check out none-ls
};
onAttach = ''
vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')
''; # Seems needed for auto-completion with nvim-compe
};
nvim-lightbulb = {
# Shows a lightbulb whenever a codeAction is available under the cursor
enable = true;
autocmd.enabled = true;
};
lspkind.enable = true; # Add icons to LSP completions
# Treesitter
treesitter = {
# Allows for better syntax highlighting
enable = true;
incrementalSelection = {
enable = true;
};
# indent = true; # Not very working last time I tried apparently
};
# TODO Investigate https://github.com/nvim-treesitter/nvim-treesitter-textobjects
indent-blankline.enable = true; # TODO integrate with rainbow-delimiters and use more of the options
undotree.enable = true; # Navigate edition history
# Git
fugitive.enable = true; # Git basics
gitsigns.enable = true; # Show changed lines in the gutter
# Language-specific
# dap.enable = true; # Debug Adapter Protocol client # 23.11
nvim-colorizer.enable = true; # Display colors of color-codes
};
extraPlugins = with pkgs.vimPlugins; [
nvim-scrollview # Scroll bar
# Status line
feline-nvim # Customizable status line.
# TODO Abandonned. Maybe use lualine?
# Search/replace
vim-abolish # Regex for words, with case in mind
vim-easy-align # Aligning lines around a certain character
# Surrounding pairs
targets-vim # Better interaction with surrounding pairs
# f/F mode
vim-shot-f # Highlight relevant characters for f/F/t/T modes
quick-scope # Highlight relevant characters for f/F modes one per word but always
# Registers
registers-nvim # Show register content when pressing "
# TODO Doesn't work. Didn't work on Arch either
# Tags
vim-gutentags # Generate tags
symbols-outline-nvim # Show a symbol panel on the right
# TODO Fails on startup. Same on Arch. Config issue?
# Language server
lsp_signature-nvim # Show argument definition when typing a function
# Treesitter
nvim-ts-rainbow # Randomly color parenthesis pairs
# TODO Replace with plugins.rainbow-delimiters
# Snippets
vim-vsnip
vim-vsnip-integ
friendly-snippets
# Auto-completion
nvim-compe
# TODO Archived. Maybe use nvim-cmp and plugins instead?
# Git
fugitive-gitlab-vim # Open files in GitLab
# TODO Connect it!
# Language-specific
tcomment_vim # Language-aware (un)commenting
] ++ lib.optionals config.frogeye.extra [
vim-LanguageTool # Check grammar for human languages
] ++ lib.optionals config.programs.pandoc.enable [
vim-pandoc # Pandoc-specific stuff because there's no LSP for it
vim-pandoc-syntax
] ++ lib.optionals config.frogeye.dev.c [
nvim-dap # Debug Adapter Protocol client
] ++ lib.optionals config.frogeye.dev.ansible [
ansible-vim # TODO Doesn't have snippets
];
extraConfigLua = lib.strings.concatMapStringsSep "\n" (f: builtins.readFile f) [
./vim/feline.lua
./vim/symbols-outline-nvim.lua
./vim/lsp_signature-nvim.lua
./vim/nvim-ts-rainbow.lua
./vim/nvim-compe.lua
];
extraConfigVim = ''
" GENERAL
" Avoid showing message extra message when using completion
set shortmess+=c
command Reload source $MYVIMRC
" PLUGINS
" vim-gutentags
let g:gutentags_cache_dir = expand('~/.cache/nvim/tags')
" nvim-compe
" Copy-pasted because I couldn't be bothered
set completeopt=menuone,noselect
inoremap <silent><expr> <C-Space> compe#complete()
inoremap <silent><expr> <CR> compe#confirm('<CR>')
inoremap <silent><expr> <C-e> compe#close('<C-e>')
inoremap <silent><expr> <C-f> compe#scroll({ 'delta': +4 })
inoremap <silent><expr> <C-d> compe#scroll({ 'delta': -4 })
'' + lib.optionalString config.frogeye.extra ''
" languagetool
let g:languagetool_cmd = "${pkgs.languagetool}/bin/languagetool-commandline"
" TODO Doesn't work
'' + lib.optionalString config.programs.pandoc.enable ''
" vim-pandox
let g:pandoc#modules#disabled = ["folding"]
let g:pandoc#spell#enabled = 0
let g:pandoc#syntax#conceal#use = 0
'';
autoCmd = [
# Turn off relativenumber only for insert mode
{ event = "InsertEnter"; pattern = "*"; command = "set norelativenumber"; }
{ event = "InsertLeave"; pattern = "*"; command = "set relativenumber"; }
# Additional extensions
{ event = "BufRead"; pattern = "*.jinja"; command = "set filetype=jinja2"; } # TODO Probably GH-specific?
{ event = "BufNewFile"; pattern = "*.jinja"; command = "set filetype=jinja2"; }
# vim-easy-align: Align Markdown tables
{ event = "FileType"; pattern = "markdown"; command = "vmap <Bar> :EasyAlign*<Bar><Enter>"; }
];
userCommands = {
# Reload = { command = "source $MYVIRMC"; };
# TODO Is not working, options is set to nil even though it shouldn't
};
keymaps = [
# GENERAL
# Allow saving of files as sudo when I forgot to start vim using sudo.
# From https://stackoverflow.com/a/7078429
{ mode = "c"; key = "w!!"; action = "w !sudo tee > /dev/null %"; }
{ mode = "i"; key = "jk"; action = "<Esc>"; }
{ mode = "v"; key = "<Enter>"; action = "<Esc>"; }
{ key = "<Enter>"; action = "o<Esc>"; }
# { key = "<C-H>"; action = ":bp<CR>"; }
# { key = "<C-L>"; action = ":bn<CR>"; }
{ key = "<C-K>"; action = "kkkkkkkkkkkkkkkkkkkkk"; }
{ key = "<C-J>"; action = "jjjjjjjjjjjjjjjjjjjjj"; }
# \s to replace globally the word under the cursor
{ key = "<Leader>s"; action = ":%s/\\<<C-r><C-w>\\>/"; }
# PLUGINS
# barbar
{ key = "<C-H>"; action = "<Cmd>BufferPrevious<CR>"; options = { silent = true; }; }
{ key = "<C-L>"; action = "<Cmd>BufferNext<CR>"; options = { silent = true; }; }
# TODO https://www.reddit.com/r/neovim/comments/mbj8m5/how_to_setup_ctrlshiftkey_mappings_in_neovim_and/
{ key = "<Space><C-H>"; action = "<Cmd>BufferMovePrevious<CR>"; options = { silent = true; }; }
{ key = "<Space><C-L>"; action = "<Cmd>BufferMoveNext<CR>"; options = { silent = true; }; }
# TODO gotos don't work
{ key = "<C-1>"; action = "<Cmd>BufferGoto 1<CR>"; options = { silent = true; }; }
{ key = "<C-2>"; action = "<Cmd>BufferGoto 2<CR>"; options = { silent = true; }; }
{ key = "<C-3>"; action = "<Cmd>BufferGoto 3<CR>"; options = { silent = true; }; }
{ key = "<C-4>"; action = "<Cmd>BufferGoto 4<CR>"; options = { silent = true; }; }
{ key = "<C-5>"; action = "<Cmd>BufferGoto 5<CR>"; options = { silent = true; }; }
{ key = "<C-6>"; action = "<Cmd>BufferGoto 6<CR>"; options = { silent = true; }; }
{ key = "<C-7>"; action = "<Cmd>BufferGoto 7<CR>"; options = { silent = true; }; }
{ key = "<C-8>"; action = "<Cmd>BufferGoto 8<CR>"; options = { silent = true; }; }
{ key = "<C-9>"; action = "<Cmd>BufferGoto 9<CR>"; options = { silent = true; }; }
{ key = "<C-0>"; action = "<Cmd>BufferLast<CR>"; options = { silent = true; }; }
{ key = "gb"; action = "<Cmd>BufferPick<CR>"; options = { silent = true; }; }
# TODO Other useful options?
# symbols-outline-nvim
{ key = "<Space>s"; action = "<Cmd>SymbolsOutline<CR>"; options = { silent = true; }; }
# undotree
{ key = "<Space>u"; action = "<Cmd>UndotreeToggle<CR>"; options = { silent = true; }; }
];
};
}

View file

@ -1,77 +0,0 @@
{ pkgs, lib, config, ... }:
let
# UPST
vim-shot-f = pkgs.vimUtils.buildVimPlugin {
pname = "vim-shot-f";
version = "2016-02-05";
src = pkgs.fetchFromGitHub {
owner = "deris";
repo = "vim-shot-f";
rev = "eea71d2a1038aa87fe175de9150b39dc155e5e7f";
sha256 = "iAPvIs/lhW+w5kFTZKaY97D/kfCGtqKrJVFvZ8cHu+c=";
};
meta.homepage = "https://github.com/deris/vim-shot-f";
};
quick-scope = pkgs.vimUtils.buildVimPlugin rec {
pname = "quick-scope";
version = "2.6.1";
src = pkgs.fetchFromGitHub {
owner = "unblevable";
repo = "quick-scope";
rev = "v${version}";
sha256 = "TcA4jZIdnQd06V+JrXGiCMr0Yhm9gB6OMiTSdzMt/Qw=";
};
meta.homepage = "https://github.com/unblevable/quick-scope";
};
in
{
config = {
programs.nixvim = {
extraPlugins = with pkgs.vimPlugins; [
# f/F mode
vim-shot-f # Highlight relevant characters for f/F/t/T modes
quick-scope # Highlight relevant characters for f/F modes one per word but always
];
options = {
# From https://www.hillelwayne.com/post/intermediate-vim/
scrolloff = 10;
lazyredraw = true; # Do not redraw screen in the middle of a macro. Makes them complete faster.
cursorcolumn = true;
# From http://stackoverflow.com/a/5004785/2766106
list = true;
listchars = "tab:,trail:·,extends:,precedes:,nbsp:_";
showbreak = "";
};
plugins = {
# Underline all instances of the underlined word
cursorline = {
enable = true;
cursorline.enable = false;
};
# Catches attention when cursor changed position
specs = {
enable = true;
min_jump = 5;
fader = { builtin = "pulse_fader"; };
resizer = { builtin = "shrink_resizer"; };
};
# Treesitter
treesitter = {
# Allows for better syntax highlighting
enable = true;
incrementalSelection = {
enable = true;
};
# indent = true; # Not very working last time I tried apparently
};
indent-blankline.enable = true; # Show indent guides
rainbow-delimiters.enable = true; # Randomly colore paired brackets
nvim-colorizer.enable = true; # Display colors of color-codes
};
};
};
}

View file

@ -1,54 +0,0 @@
{ pkgs, lib, config, ... }:
{
config = {
# Completion
programs.nixvim = {
extraConfigLuaPre = builtins.readFile ./completion_pre.lua;
plugins = {
# Snippets
# UltiSnips should be the better snippet engine, but:
# - Not built-in into Nixvim yet (UPST?)
# - Couldn't manage to make it work with friendly-snippets, which seems to give better snippets for Python at least
# - Tab switching between fields seems hard to configure
luasnip = {
enable = true;
fromVscode = [
{ paths = "${pkgs.vimPlugins.friendly-snippets}"; }
# { paths = "${pkgs.vimPlugins.vim-snippets}"; } # UPST Needs snipmate support
];
};
# Completion
nvim-cmp = {
enable = true;
mapping = {
# Proposed example, since there's no default
"<C-Space>" = "cmp.mapping.complete()";
"<C-d>" = "cmp.mapping.scroll_docs(-4)";
"<C-e>" = "cmp.mapping.close()";
"<C-f>" = "cmp.mapping.scroll_docs(4)";
"<CR>" = "cmp.mapping.confirm({ select = true })";
"<S-Tab>" = {
action = "nvim_cmp_stab";
modes = [ "i" "s" ];
};
"<Tab>" = {
action = "nvim_cmp_tab";
modes = [ "i" "s" ];
};
};
sources = [
# Respective plugins will get installed automatically
{ name = "buffer"; }
{ name = "calc"; }
{ name = "nvim_lsp"; }
{ name = "path"; }
{ name = "luasnip"; }
];
snippet.expand = "luasnip";
};
lspkind.enable = true; # Add icons to LSP completions
};
};
};
}

View file

@ -1,32 +0,0 @@
-- https://github.com/hrsh7th/nvim-cmp/wiki/Example-mappings#luasnip
local has_words_before = function()
unpack = unpack or table.unpack
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end
local luasnip = require("luasnip")
local cmp = require("cmp")
local nvim_cmp_tab = function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif luasnip.expand_or_jumpable() then
luasnip.expand_or_jump()
elseif has_words_before() then
cmp.complete()
else
fallback()
end
end
local nvim_cmp_stab = function(fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif luasnip.jumpable(-1) then
luasnip.jump(-1)
else
fallback()
end
end

View file

@ -1,160 +0,0 @@
{ pkgs, lib, config, ... }:
{
config = {
programs = {
# https://www.reddit.com/r/neovim/comments/mbj8m5/how_to_setup_ctrlshiftkey_mappings_in_neovim_and/
alacritty.settings.key_bindings = [
{ key = "H"; mods = "Control|Shift"; chars = "\\x1b[72;5u"; }
{ key = "L"; mods = "Control|Shift"; chars = "\\x1b[76;5u"; }
] ++ (map
(n: { key = "Key${builtins.toString n}"; mods = "Control"; chars = "\\x1b[${builtins.toString (48+n)};5u"; })
(lib.lists.range 0 9));
# Ctrl+<number> doesn't get interpreted, but Ctrl+Shift+<number> does, so let's use that
nixvim = {
autoCmd = [
# Turn off relativenumber only for insert mode
{ event = "InsertEnter"; pattern = "*"; command = "set norelativenumber"; }
{ event = "InsertLeave"; pattern = "*"; command = "set relativenumber"; }
];
extraPlugins = with pkgs.vimPlugins; [
nvim-scrollview # Scroll bar
];
keymaps =
let
options = { silent = true; };
in
[
# barbar
{ key = "gb"; action = "<Cmd>BufferPick<CR>"; inherit options; }
{ key = "<C-H>"; action = "<Cmd>BufferPrevious<CR>"; inherit options; }
{ key = "<C-L>"; action = "<Cmd>BufferNext<CR>"; inherit options; }
{ key = "<C-S-H>"; action = "<Cmd>BufferMovePrevious<CR>"; inherit options; }
{ key = "<C-S-L>"; action = "<Cmd>BufferMoveNext<CR>"; inherit options; }
{ key = "<C-0>"; action = "<Cmd>BufferLast<CR>"; inherit options; }
] ++ (map
(n: { key = "<C-${builtins.toString n}>"; action = "<Cmd>BufferGoto ${builtins.toString n}<CR>"; inherit options; })
(lib.lists.range 1 9));
options = {
showmode = false;
number = true;
relativenumber = true;
title = true;
};
plugins = {
# Tabline
barbar.enable = true;
# TODO Reload make it use the preset colorscheme
# Status line
lualine = with config.lib.stylix.colors.withHashtag; let
normal = { fg = base05; bg = base01; };
inverted = { fg = base00; bg = base03; };
normal_ina = { fg = base02; bg = base01; };
inverted_ina = { fg = base00; bg = base02; };
in
rec {
enable = true;
inactiveSections = sections;
sections = {
lualine_a = [{
name = ''string.format('%d', vim.fn.line('$'))'';
}];
lualine_b = [
"mode"
];
lualine_c = [{
name = "filename";
color = {
__raw = ''
function(section)
return { fg = vim.bo.modified and '${base08}' or '${normal.fg}' }
end
'';
};
extraConfig = {
path = 1; # Relative path
symbols = {
modified = "";
newfile = "󰻭";
readonly = "󰏯";
unnamed = "󱀶";
};
};
}
"location"];
lualine_x = [{
name = ''(next(vim.lsp.buf_get_clients()) == nil) and "󰒲 " or ""'';
extraConfig.separator = { left = ""; right = ""; };
}] ++ (lib.mapAttrsToList
(diag_name: diag_color: {
name = "diagnostics";
extraConfig = {
color.bg = diag_color;
colored = false;
separator = { left = ""; right = ""; };
sections = [ diag_name ];
};
})
{
error = base08;
warn = base0A;
hint = base0C;
info = base0B;
});
lualine_y = [{
name = "diff";
extraConfig = {
diff_color = {
added.fg = base0B;
modified.fg = base0A;
removed.fg = base08;
};
symbols = {
added = " ";
modified = " ";
removed = " ";
};
};
}
"branch"];
lualine_z = [
"filetype"
"fileformat"
"encoding"
];
};
theme = (lib.mapAttrs
(mode_name: mode_color: {
a = inverted;
b = inverted // { bg = mode_color; gui = "bold"; };
c = normal;
x = inverted;
y = normal;
z = inverted // { bg = mode_color; };
})
{
normal = base0D;
insert = base0B;
visual = base0F;
replace = base08;
command = base0E;
}) // {
inactive = {
a = inverted_ina;
b = normal_ina // { bg = base00; gui = "bold"; };
c = normal_ina;
x = inverted_ina;
y = normal_ina;
z = normal_ina // { bg = base00; };
};
};
};
# Show context on top if scrolled out
treesitter-context = {
enable = true;
maxLines = 5;
};
};
};
};
};
}

View file

@ -1,145 +0,0 @@
{ pkgs, lib, config, nixvim, ... }:
{
# config = lib.mkIf config.programs.nixvim.enable { # Somehow this is infinite recursion?
config = {
home.sessionVariables = {
EDITOR = "nvim";
} // lib.optionalAttrs config.frogeye.desktop.xorg {
VISUAL = "nvim";
};
programs.bash.shellAliases = {
vi = "nvim";
vim = "nvim";
};
programs.nixvim = {
# Required, otherwise light mode becomes a default dark theme.
colorschemes.base16.colorscheme = "solarized-${config.stylix.polarity}";
options = {
ignorecase = true;
smartcase = true;
gdefault = true;
tabstop = 4;
shiftwidth = 4;
expandtab = true;
splitbelow = true;
visualbell = true;
updatetime = 250;
undofile = true;
wildmode = "longest:full,full";
wildmenu = true;
};
globals = {
netrw_fastbrowse = 0; # Close the file explorer once you select a file
};
plugins = {
# Go to whatever
telescope = {
enable = true;
keymaps = {
gF = "find_files";
gf = "git_files";
gB = "buffers";
gl = "current_buffer_fuzzy_find";
gL = "live_grep";
gT = "tags";
gt = "treesitter";
gm = "marks";
gh = "oldfiles";
gH = "command_history";
gS = "search_history";
gC = "commands";
};
defaults = {
vimgrep_arguments = [
"${pkgs.ripgrep}/bin/rg"
"--color=never"
"--no-heading"
"--with-filename"
"--line-number"
"--column"
"--smart-case"
];
};
extensions.fzf-native = {
enable = true;
caseMode = "smart_case";
fuzzy = true;
overrideFileSorter = true;
overrideGenericSorter = true;
};
};
# TODO Go to any symbol in the current working directory, for when LSP doesn't support it.
# Or at least something to live_grep the curent word.
# Surrounding pairs
surround.enable = true; # Change surrounding pairs (e.g. brackets, quotes)
undotree.enable = true; # Navigate edition history
};
extraPlugins = with pkgs.vimPlugins; [
# Search/replace
vim-abolish # Regex for words, with case in mind
vim-easy-align # Aligning lines around a certain character
# Surrounding pairs
targets-vim # Better interaction with surrounding pairs
# Language-specific
tcomment_vim # Language-aware (un)commenting
] ++ lib.optionals config.frogeye.dev.ansible [
ansible-vim
# Doesn't generate snippets, but those are for UltiSnip anyways
];
extraConfigVim = ''
" Avoid showing message extra message when using completion
set shortmess+=c
'';
userCommands = {
Reload = { command = "source ${config.xdg.configHome}/nvim/init.lua"; force = false; };
# 24.05 force=false was for https://github.com/nix-community/nixvim/issues/954
};
keymaps = [
# GENERAL
# Allow saving of files as sudo when I forgot to start vim using sudo.
# From https://stackoverflow.com/a/7078429
{ mode = "c"; key = "w!!"; action = "w !sudo tee > /dev/null %"; }
{ mode = "i"; key = "jk"; action = "<Esc>"; }
{ mode = "v"; key = "<Enter>"; action = "<Esc>"; }
{ key = "<Enter>"; action = "o<Esc>"; }
# { key = "<C-H>"; action = ":bp<CR>"; }
# { key = "<C-L>"; action = ":bn<CR>"; }
{ key = "<C-K>"; action = "kkkkkkkkkkkkkkkkkkkkk"; }
{ key = "<C-J>"; action = "jjjjjjjjjjjjjjjjjjjjj"; }
# \s to replace globally the word under the cursor
{ key = "<Leader>s"; action = ":%s/\\<<C-r><C-w>\\>/"; }
# PLUGINS
# undotree
{ key = "<Space>u"; action = "<Cmd>UndotreeToggle<CR>"; options = { silent = true; }; }
];
};
};
imports = [
nixvim.homeManagerModules.nixvim
./code.nix
./completion.nix
./decoration.nix
./git.nix
./lsp.nix
];
}

165
hm/vim/feline.lua Normal file
View file

@ -0,0 +1,165 @@
vim.cmd([[
set noshowmode
set laststatus=2
]])
local base16_colors = require('base16-colorscheme').colors
local vi_mode_utils = require('feline.providers.vi_mode')
local lsp = require('feline.providers.lsp')
require('feline').setup({
default_bg = 'base01',
default_fg = 'base04',
theme = {
base00 = base16_colors.base00,
base01 = base16_colors.base01,
base02 = base16_colors.base02,
base03 = base16_colors.base03,
base04 = base16_colors.base04,
base05 = base16_colors.base05,
base06 = base16_colors.base06,
base07 = base16_colors.base07,
base08 = base16_colors.base08,
base09 = base16_colors.base09,
base0A = base16_colors.base0A,
base0B = base16_colors.base0B,
base0C = base16_colors.base0C,
base0D = base16_colors.base0D,
base0E = base16_colors.base0E,
base0F = base16_colors.base0F,
},
components = {
active = {
{
{
provider = function() return string.format(' %d ', vim.fn.line('$')) end,
-- If you can, make it depend on the actual bar size
left_sep = {
{str = 'block', fg = 'base05'}
},
hl = {
fg = 'base01',
bg = 'base04',
},
},
{
provider = 'vi_mode',
hl = function()
return {
name = vi_mode_utils.get_mode_highlight_name(),
bg = vi_mode_utils.get_mode_color(),
fg = 'white',
style = 'bold',
}
end,
left_sep = {''},
right_sep = {''},
},
{
provider='',
hl = function()
return {
bg = vi_mode_utils.get_mode_color(),
fg = (vim.bo.modified and 'base09') or 'base0D',
}
end,
},
{
provider = 'file_info',
type = 'relative',
hl = function()
return {
fg = 'base06',
bg = (vim.bo.modified and 'base09') or 'base0D',
style = 'bold',
}
end,
left_sep = {''},
right_sep = {''},
},
{
provider='',
hl = function()
return {
bg = 'base02',
fg = (vim.bo.modified and 'base09') or 'base0D',
}
end,
},
{
provider = 'position',
hl = { fg = 'base05', bg = 'base02' },
right_sep = {''},
},
-- If it miraculously became easy to do, add LSP position here
{
provider='',
hl = { bg = 'base01', fg = 'base02' },
},
},
{
{
provider='',
hl = { bg = 'base03', fg = 'base01', },
},
{
provider='z',
enabled = function() return next(vim.lsp.buf_get_clients()) == nil end,
hl = { bg = 'base03', fg = 'base01', },
left_sep = '',
},
{
provider = 'diagnostic_errors',
enabled = function() return lsp.diagnostics_exist(vim.diagnostic.severity.ERROR) end,
hl = { fg = 'red', bg = 'base03', },
left_sep = '',
},
{
provider = 'diagnostic_warnings',
enabled = function() return lsp.diagnostics_exist(vim.diagnostic.severity.WARN) end,
hl = { fg = 'yellow', bg = 'base03', },
left_sep = '',
},
{
provider = 'diagnostic_hints',
enabled = function() return lsp.diagnostics_exist(vim.diagnostic.severity.HINT) end,
hl = { fg = 'cyan', bg = 'base03', },
left_sep = '',
},
{
provider = 'diagnostic_info',
enabled = function() return lsp.diagnostics_exist(vim.diagnostic.severity.INFO) end,
hl = { fg = 'skyblue', bg = 'base03', },
left_sep = '',
},
{
provider='█',
hl = { bg = 'base02', fg = 'base03', },
},
{
provider = 'git_diff_added',
hl = { fg = 'green', bg = 'base02', },
left_sep = '',
enabled = function() return vim.b.gitsigns_status_dict end,
},
{
provider = 'git_diff_changed',
hl = { fg = 'orange', bg = 'base02', },
left_sep = '',
enabled = function() return vim.b.gitsigns_status_dict end,
},
{
provider = 'git_diff_removed',
hl = { fg = 'red', bg = 'base02', },
left_sep = '',
enabled = function() return vim.b.gitsigns_status_dict end,
},
{
provider = 'git_branch',
hl = { fg = 'base05', bg = 'base02', style = 'bold', },
right_sep = '',
left_sep = '',
enabled = function() return vim.b.gitsigns_status_dict end,
},
}
},
}
})

Some files were not shown because too many files have changed in this diff Show more