1

Home: Rename home/modules to home/homemodules

This commit is contained in:
2026-01-18 15:34:36 +01:00
parent 25e9128875
commit d12b247368
117 changed files with 1 additions and 1 deletions

View File

@ -0,0 +1,14 @@
{
config,
nixosConfig,
lib,
mylib,
pkgs,
...
}: let
inherit (config.modules) TEMPLATE color;
in {
options.modules.TEMPLATE = import ./options.nix {inherit lib mylib;};
config = lib.mkIf TEMPLATE.enable {};
}

View File

@ -0,0 +1,7 @@
{
lib,
mylib,
...
}: {
enable = lib.mkEnableOption "TEMPLATE";
}

View File

@ -0,0 +1,2 @@
node_modules/
@girs/

View File

@ -0,0 +1,10 @@
import { App } from "astal/gtk4"
import style from "./style.scss"
import Bar from "./widget/Bar"
App.start({
css: style,
main() {
App.get_monitors().map(Bar)
},
})

View File

@ -0,0 +1,21 @@
declare const SRC: string
declare module "inline:*" {
const content: string
export default content
}
declare module "*.scss" {
const content: string
export default content
}
declare module "*.blp" {
const content: string
export default content
}
declare module "*.css" {
const content: string
export default content
}

View File

@ -0,0 +1,6 @@
{
"name": "astal-shell",
"dependencies": {
"astal": "/home/christoph/.local/share/ags"
}
}

View File

@ -0,0 +1,46 @@
// Import the colors exported by the nixos config
// TODO: Depend on username somehow...
@use "/home/christoph/.config/colors" as *;
// https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gtk/theme/Adwaita/_colors-public.scss
$fg-color: #{"@theme_fg_color"};
$bg-color: #{"@theme_bg_color"};
// Order is Top-Right-Bottom-Left for combined properties
* {
// Remove the default theme's background-image, otherwise background-color doesn't work
background-image: none;
// Clear implicit paddings and margins, otherwise size management is terrible
padding: 0;
margin: 0;
}
.Window {
background: transparent;
font-weight: bold;
font-size: x-large;
.Bar {
background-color: rgba($light-base, 0.3);
border-radius: 6px;
border-width: 2px;
border-color: $dark-lavender;
border-style: solid;
margin: 10px 10px 0 10px;
.LauncherButton {
background-color: $dark-lavender;
border-radius: 6px;
border-width: 0;
margin: -1px 10px -1px -1px; // Negative margins to remove gaps from border radii
min-width: 36px;
min-height: 36px;
>label {
margin-left: -4px; // Tux not centered otherwise
}
}
}
}

View File

@ -0,0 +1,14 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"experimentalDecorators": true,
"strict": true,
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "Bundler",
// "checkJs": true,
// "allowJs": true,
"jsx": "react-jsx",
"jsxImportSource": "astal/gtk4",
}
}

View File

@ -0,0 +1,76 @@
import { App, Astal, Gtk, Gdk } from "astal/gtk4"
import { GLib, Variable } from "astal"
import { SysTray } from "./SysTray";
const user = Variable("")
.poll(60000, ["bash", "-c", "whoami"]);
const time = Variable("")
.poll(1000, ["bash", "-c", "date +'%H:%M:%S'"]);
const date = Variable("")
.poll(60000, ["bash", "-c", "date +'%y-%m-%d'"])
const uptime = Variable("")
.poll(60000, ["bash", "-c", "uptime | awk -F'( |,)+' '{print $4}'"]);
export default function Bar(gdkmonitor: Gdk.Monitor) {
const { TOP, LEFT, RIGHT } = Astal.WindowAnchor
return <window
cssClasses={["Window"]}
application={App}
gdkmonitor={gdkmonitor}
exclusivity={Astal.Exclusivity.EXCLUSIVE}
anchor={TOP | LEFT | RIGHT}
visible
child={
<centerbox
cssClasses={["Bar"]}
startWidget={
<box
halign={Gtk.Align.START}
children={[
<button
cssClasses={["LauncherButton"]}
onClicked="rofi -drun-show-actions -show drun"
cursor={Gdk.Cursor.new_from_name("pointer", null)}
label={""}
/>,
<label
cssClasses={["UserLabel"]}
label={user((value) => `${value.toUpperCase()}`)}
/>,
<label
cssClasses={["UptimeLabel"]}
label={uptime((value) => `${value}`)}
/>,
<label
cssClasses={["WindowNameLabel"]}
label={"WINDOW"}
/>
]}
/>
}
centerWidget={
<box />
}
endWidget={
<box
halign={Gtk.Align.START}
children={[
<SysTray />
]}
/>
}
/>
}
/>
}

View File

@ -0,0 +1,40 @@
import { Variable, bind } from "astal";
import { Gtk } from "astal/gtk4"
import AstalTray from "gi://AstalTray";
export function SysTray() {
const tray = AstalTray.get_default()
const trayIcons = Variable.derive(
[bind(tray, "items")],
(items) => {
return items.map((item) => {
return (
<menubutton
item={item}
child={
<image gicon={bind(item, "gicon")} />
}
/>
);
});
},
);
return <box
cssClasses={["SysTray"]}
children={
bind(tray, "items").as(items => items.map(item => (
<menubutton
tooltipMarkup={bind(item, "tooltipMarkup")}
usePopover={false}
actionGroup={bind(item, "actionGroup").as(ag => ["dbusmenu", ag])}
menuModel={bind(item, "menuModel")}
child={
<image gicon={bind(item, "gicon")} />
}
/>
)))
}
/>
}

View File

@ -0,0 +1,130 @@
{
inputs,
config,
lib,
mylib,
pkgs,
...
}: let
inherit (config.modules) ags;
in {
options.modules.ags = import ./options.nix {inherit lib mylib;};
config = lib.mkIf ags.enable {
programs.ags = {
enable = true;
systemd.enable = false; # Currently only supports GTK3, use own service below
# AGS libs go here
extraPackages = [
inputs.ags.packages.${pkgs.stdenv.hostPlatform.system}.apps
inputs.ags.packages.${pkgs.stdenv.hostPlatform.system}.auth
inputs.ags.packages.${pkgs.stdenv.hostPlatform.system}.battery
inputs.ags.packages.${pkgs.stdenv.hostPlatform.system}.bluetooth
inputs.ags.packages.${pkgs.stdenv.hostPlatform.system}.cava
# inputs.ags.packages.${pkgs.stdenv.hostPlatform.system}.greet
inputs.ags.packages.${pkgs.stdenv.hostPlatform.system}.hyprland
inputs.ags.packages.${pkgs.stdenv.hostPlatform.system}.mpris
inputs.ags.packages.${pkgs.stdenv.hostPlatform.system}.network
inputs.ags.packages.${pkgs.stdenv.hostPlatform.system}.notifd
# inputs.ags.packages.${pkgs.stdenv.hostPlatform.system}.powerprofiles
# inputs.ags.packages.${pkgs.stdenv.hostPlatform.system}.river
inputs.ags.packages.${pkgs.stdenv.hostPlatform.system}.tray
inputs.ags.packages.${pkgs.stdenv.hostPlatform.system}.wireplumber
];
# This should symlink but doesn't, it copies the files :/
# configDir = ./config;
};
# The ags module doesn't expose the "astal" cli tool or extraPackages
home.packages =
[
inputs.ags.packages.${pkgs.stdenv.hostPlatform.system}.io
]
++ config.programs.ags.extraPackages;
systemd.user.services.ags = {
Unit = {
Description = "AGS - Tool for scaffolding Astal+TypeScript projects.";
Documentation = "https://github.com/Aylur/ags";
PartOf = ["graphical-session.target"];
After = ["graphical-session-pre.target"];
};
Service = {
ExecStart = "${config.programs.ags.finalPackage}/bin/ags run --gtk4";
Restart = "on-failure";
KillMode = "mixed";
};
Install = {
WantedBy = ["graphical-session.target"];
};
};
home.file = {
# Keep this symlinked as long as I'm configuring (not required anymore since I can start AGS locally)
# ".config/ags".source = config.lib.file.mkOutOfStoreSymlink "${config.paths.nixflake}/home/modules/ags/config";
# NOTE: Don't symlink to ~/.config/ags/colors.scss, since that is already used by configDir
".config/_colors.scss".text = with config.modules.color.hex; ''
$dark-rosewater: #${dark.rosewater};
$dark-flamingo: #${dark.flamingo};
$dark-pink: #${dark.pink};
$dark-mauve: #${dark.mauve};
$dark-red: #${dark.red};
$dark-maroon: #${dark.maroon};
$dark-peach: #${dark.peach};
$dark-yellow: #${dark.yellow};
$dark-green: #${dark.green};
$dark-teal: #${dark.teal};
$dark-sky: #${dark.sky};
$dark-sapphire: #${dark.sapphire};
$dark-blue: #${dark.blue};
$dark-lavender: #${dark.lavender};
$dark-text: #${dark.text};
$dark-subtext1: #${dark.subtext1};
$dark-subtext0: #${dark.subtext0};
$dark-overlay2: #${dark.overlay2};
$dark-overlay1: #${dark.overlay1};
$dark-overlay0: #${dark.overlay0};
$dark-surface2: #${dark.surface2};
$dark-surface1: #${dark.surface1};
$dark-surface0: #${dark.surface0};
$dark-base: #${dark.base};
$dark-mantle: #${dark.mantle};
$dark-crust: #${dark.crust};
$light-rosewater: #${light.rosewater};
$light-flamingo: #${light.flamingo};
$light-pink: #${light.pink};
$light-mauve: #${light.mauve};
$light-red: #${light.red};
$light-maroon: #${light.maroon};
$light-peach: #${light.peach};
$light-yellow: #${light.yellow};
$light-green: #${light.green};
$light-teal: #${light.teal};
$light-sky: #${light.sky};
$light-sapphire: #${light.sapphire};
$light-blue: #${light.blue};
$light-lavender: #${light.lavender};
$light-text: #${light.text};
$light-subtext1: #${light.subtext1};
$light-subtext0: #${light.subtext0};
$light-overlay2: #${light.overlay2};
$light-overlay1: #${light.overlay1};
$light-overlay0: #${light.overlay0};
$light-surface2: #${light.surface2};
$light-surface1: #${light.surface1};
$light-surface0: #${light.surface0};
$light-base: #${light.base};
$light-mantle: #${light.mantle};
$light-crust: #${light.crust};
'';
};
};
}

View File

@ -0,0 +1,9 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "Enable Ags Widgets";
}

View File

@ -0,0 +1,137 @@
{
config,
lib,
mylib,
...
}:
with mylib.modules; let
cfg = config.modules.alacritty;
in {
options.modules.alacritty = import ./options.nix {inherit lib mylib;};
config = mkIf cfg.enable {
programs.alacritty = {
enable = false;
settings = {
window = {
padding = {
x = 10;
y = 10;
};
font = {
normal = "JetBrainsMono Nerd Font Mono";
size = 12;
};
};
env = {
TERM = "xterm-256color";
};
colors = {
# Default colors
primary = {
background = "#EFF1F5"; # base
foreground = "#4C4F69"; # text
# Bright and dim foreground colors
dim_foreground = "#4C4F69"; # text
bright_foreground = "#4C4F69"; # text
};
# Cursor colors
cursor = {
text = "#EFF1F5"; # base
cursor = "#DC8A78"; # rosewater
};
vi_mode_cursor = {
text = "#EFF1F5"; # base
cursor = "#7287FD"; # lavender
};
# Search colors
search = {
matches = {
foreground = "#EFF1F5"; # base
background = "#6C6F85"; # subtext0
};
focused_match = {
foreground = "#EFF1F5"; # base
background = "#40A02B"; # green
};
footer_bar = {
foreground = "#EFF1F5"; # base
background = "#6C6F85"; # subtext0
};
};
# Keyboard regex hints
hints = {
start = {
foreground = "#EFF1F5"; # base
background = "#DF8E1D"; # yellow
};
end = {
foreground = "#EFF1F5"; # base
background = "#6C6F85"; # subtext0
};
};
# Selection colors
selection = {
text = "#EFF1F5"; # base
background = "#DC8A78"; # rosewater
};
# Normal colors
normal = {
black = "#5C5F77"; # subtext1
red = "#D20F39"; # red
green = "#40A02B"; # green
yellow = "#DF8E1D"; # yellow
blue = "#1E66F5"; # blue
magenta = "#EA76CB"; # pink
cyan = "#179299"; # teal
white = "#ACB0BE"; # surface2
};
# Bright colors
bright = {
black = "#6C6F85"; # subtext0
red = "#D20F39"; # red
green = "#40A02B"; # green
yellow = "#DF8E1D"; # yellow
blue = "#1E66F5"; # blue
magenta = "#EA76CB"; # pink
cyan = "#179299"; # teal
white = "#BCC0CC"; # surface1
};
# Dim colors
dim = {
black = "#5C5F77"; # subtext1
red = "#D20F39"; # red
green = "#40A02B"; # green
yellow = "#DF8E1D"; # yellow
blue = "#1E66F5"; # blue
magenta = "#EA76CB"; # pink
cyan = "#179299"; # teal
white = "#ACB0BE"; # surface2
};
indexed_colors = [
{
index = 16;
color = "#FE640B";
}
{
index = 17;
color = "#DC8A78";
}
];
};
};
};
};
}

View File

@ -0,0 +1,9 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "Enable Alacritty";
}

View File

@ -0,0 +1,166 @@
{
config,
nixosConfig,
lib,
mylib,
pkgs,
...
}:
with lib;
with mylib.modules; let
cfg = config.modules.audio;
cfgfp = config.modules.flatpak;
in {
imports = [
../flatpak
];
options.modules.audio = import ./options.nix {inherit lib mylib;};
config = mkIf cfg.enable {
assertions = [
(mkIf cfg.bottles.enable {
assertion = cfgfp.enable;
message = "Cannot enable Bottles without the flatpak module!";
})
];
# Use builtins.concatLists instead of mkMerge as this is more safe as the type is specified,
# also mkMerge doesn't work in every case as it yields a set
home.packages = with pkgs;
builtins.concatLists [
# lib.optional is preferred over mkIf or if...then...else by nix coding standards
# lib.optional wraps its argument in a list, lib.optionals doesn't
# This means that lib.optional can be used for single packages/arguments
# and lib.optionals has to be used when the argument is itself a list
# I use lib.optionals everywhere as I think this is more clear
# Some of these include gamemode as I use that to enable performance governors for CPU/GPU and other stuff
# Enable some default pipewire stuff if pipewire is enabled
(optionals nixosConfig.services.pipewire.enable [
# TODO: Disabled on 03.02.2023 because of temporary build error
# helvum
])
(optionals cfg.carla.enable [carla gamemode])
(optionals cfg.bitwig.enable [
bitwig-studio
gamemode
])
(optionals cfg.tenacity.enable [tenacity])
(optionals cfg.faust.enable [faust])
(optionals cfg.yabridge.enable [yabridge yabridgectl])
(optionals cfg.noisesuppression.noisetorch.enable [noisetorch])
# (optionals cfg.vcvrack.enable [ vcv-rack ]) # Replaced by cardinal
(optionals cfg.cardinal.enable [cardinal])
# (optionals cfg.vital.enable [ vital-synth ]) # Replaced by distrho
(optionals cfg.distrho.enable [distrho])
];
services.easyeffects = mkIf cfg.noisesuppression.easyeffects.enable {
enable = true;
preset = optionalString cfg.noisesuppression.easyeffects.autostart "noise_supression";
};
# NOTE: This desktop entry is created in /etc/profiles/per-user/christoph/share/applications
# This location is part of XDG_DATA_DIRS
xdg.desktopEntries.guitar = mkIf cfg.carla.enable {
name = "Guitar Amp (Carla)";
genericName = "Guitar Amp Simulation";
icon = "carla";
exec = "env PIPEWIRE_LATENCY=256/48000 gamemoderun carla ${config.home.homeDirectory}/.config/carla/GuitarDefault.carxp";
terminal = false;
categories = ["Music" "Audio"];
};
xdg.desktopEntries.bitwig-low-latency = mkIf cfg.bitwig.enable {
name = "Bitwig Studio (Low Latency)";
genericName = "Digital Audio Workstation";
icon = "bitwig-studio";
exec = "env PIPEWIRE_LATENCY=256/48000 gamemoderun bitwig-studio";
terminal = false;
categories = ["Music" "Audio"];
};
# TODO: Disable only for plasma
# TODO: After pipewire.target or partof pipewire.service?
systemd.user.services = {
# autostart-noisetorch =
# (mkIf (cfg.noisesuppression.noisetorch.enable && cfg.noisesuppression.noisetorch.autostart) {
# Unit = {
# Type = "oneshot";
# Description = "Noisetorch noise suppression";
# PartOf = [ "graphical-session.target" ];
# After = [ "graphical-session.target" ];
# };
# Service = {
# Environment = "PATH=${config.home.profileDirectory}/bin"; # Leads to /etc/profiles/per-user/christoph/bin
# ExecStart = "${pkgs.noisetorch}/bin/noisetorch -i";
# Restart = "on-failure";
# };
# Install.WantedBy = [ "graphical-session.target" ];
# });
};
# NOTE: Important to not disable this option if another module enables it
modules.flatpak.bottles.enable = mkIf cfg.bottles.enable true;
home.activation = mkMerge [
# The module includes the default carla project with ArchetypePetrucci + ArchetypeGojira
(mkIf cfg.carla.enable {
linkCarlaConfig =
hm.dag.entryAfter ["writeBoundary"]
(mkLink "${config.home.homeDirectory}/NixFlake/config/carla" "${config.home.homeDirectory}/.config/carla");
})
(mkElse cfg.carla.enable {
unlinkCarlaConfig =
hm.dag.entryAfter ["writeBoundary"]
(mkUnlink "${config.home.homeDirectory}/.config/carla");
})
# Replaced by distrho
# (mkIf cfg.vital.enable {
# linkVitalVST3 = hm.dag.entryAfter [ "writeBoundary" ]
# (mkLink "${pkgs.vital-synth}/lib/vst3/Vital.vst3" "${config.home.homeDirectory}/.vst3/Vital.vst3");
# })
# (mkElse cfg.vital.enable {
# unlinkVitalVST3 = hm.dag.entryAfter [ "writeBoundary" ]
# (mkUnlink "${config.home.homeDirectory}/.vst3/Vital.vst3");
# })
(mkIf cfg.distrho.enable {
linkDistrhoLV2 =
hm.dag.entryAfter ["writeBoundary"]
(mkLink "${pkgs.distrho}/lib/lv2" "${config.home.homeDirectory}/.lv2/distrho");
linkDistrhoVST =
hm.dag.entryAfter ["writeBoundary"]
(mkLink "${pkgs.distrho}/lib/vst" "${config.home.homeDirectory}/.vst/distrho");
linkDistrhoVST3 =
hm.dag.entryAfter ["writeBoundary"]
(mkLink "${pkgs.distrho}/lib/vst3" "${config.home.homeDirectory}/.vst3/distrho");
})
(mkElse cfg.distrho.enable {
unlinkDistrhoLV2 =
hm.dag.entryAfter ["writeBoundary"]
(mkUnlink "${config.home.homeDirectory}/.lv2/distrho");
unlinkDistrhoVST =
hm.dag.entryAfter ["writeBoundary"]
(mkUnlink "${config.home.homeDirectory}/.vst/distrho");
unlinkDistrhoVST3 =
hm.dag.entryAfter ["writeBoundary"]
(mkUnlink "${config.home.homeDirectory}/.vst3/distrho");
})
(mkIf (cfg.yabridge.enable && cfg.yabridge.autoSync) {
syncYabridge = hm.dag.entryAfter ["writeBoundary"] ''
yabridgectl sync
'';
})
];
};
}

View File

@ -0,0 +1,48 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "Audio module";
# TODO: Group these in categories (like instruments/VSTs or sth)
# TODO: Make it easier to add many yes/no options, similar to the flatpak stuff
# Hosts/Editing
carla.enable = mkEnableOption "Carla (VST host)";
bitwig.enable = mkEnableOption "Bitwig (Digital audio workstation)";
tenacity.enable = mkEnableOption "Tenacity (Audacity fork)";
# Instruments/Plugins
# vcvrack.enable = mkEnableOption "VCV-Rack (Eurorack simulator)"; # Replaced by cardinal
cardinal.enable = mkEnableOption "Open Source VCV-Rack plugin wrapper";
# vital.enable = mkEnableOption "Vital (Wavetable synthesizer)"; # Replaced by distrho
distrho.enable = mkEnableOption "Distrho (Linux VST ports)";
# Misc
faust.enable = mkEnableOption "Faust (functional DSP language)";
bottles.enable = mkEnableOption "Bottles (flatpak)";
# TODO: Automatically add the needed paths, depends on the bottle though
# /home/christoph/.var/app/com.usebottles.bottles/data/bottles/bottles/Audio/drive_c/Program Files/Common Files/VST3
# /home/christoph/.var/app/com.usebottles.bottles/data/bottles/bottles/Audio/drive_c/Program Files/VstPlugins
yabridge = {
enable = mkEnableOption "Yabridge (Windows VST plugin manager)";
autoSync = mkBoolOption false "Sync yabridge plugins on nixos-rebuild";
};
noisesuppression = {
noisetorch = {
enable = mkEnableOption "Noisetorch";
autostart = mkBoolOption false "Autoload Noisetorch suppression";
};
# TODO: Store easyeffects presets/config (dconf com/github/wwmm/easyeffects ?)
easyeffects = {
enable = mkEnableOption "EasyEffects";
autostart = mkBoolOption false "Autoload EasyEffects suppression profile";
};
};
}

View File

@ -0,0 +1,130 @@
# https://nixos.org/manual/nixos/stable/index.html#sec-writing-modules
# This is a function with arguments
{
config,
lib,
mylib,
pkgs,
...
}:
# We add stuff from lib to our namespace (mkOption...)
with lib;
with mylib.modules; let
# This is the current state of the option that this module defines
# We use it to determine if the config should be changed below
cfg = config.modules.emacs;
in {
imports = [];
# Options is a vector of options this module defines
# This module defines only the "emacs" option and suboptions "enable" and "doom"
options.modules.emacs = import ./options.nix {inherit lib mylib;};
# Config is the merged set of all module configurations
# Here we define what happens to the config if the module is active (but only if the module is active)
# Since this module is for HomeManager, config is not the system config
# Attribute sets like config can be defined multiple times (every module defines a different config), on
# building the config they are merged
# Because config depends on itself recursively (through cfg) we use mkIf instead of the normal if...then...else,
# as it delays the evaluation (the if is moved inside the assignments inside the set)
# mkIf can only be used in the config section (like mkMerge, mkForce and co)
config = mkIf cfg.enable {
assertions = [
(mkIf cfg.nativeComp {
assertion = !cfg.pgtkNativeComp && !cfg.nixpkgs;
message = "Can't enable more than one Emacs package!";
})
(mkIf cfg.pgtkNativeComp {
assertion = !cfg.nativeComp && !cfg.nixpkgs;
message = "Can't enable more than one Emacs package!";
})
(mkIf cfg.nixpkgs {
assertion = !cfg.nativeComp && !cfg.pgtkNativeComp;
message = "Can't enable more than one Emacs package!";
})
];
# What home packages should be enabled
home.packages = with pkgs;
builtins.concatLists [
(optionals cfg.nativeComp [((emacsPackagesFor emacsNativeComp).emacsWithPackages (epkgs: [epkgs.vterm epkgs.pdf-tools]))])
(optionals cfg.pgtkNativeComp [((emacsPackagesFor emacsPgtkNativeComp).emacsWithPackages (epkgs: [epkgs.vterm epkgs.pdf-tools]))])
(optionals cfg.nixpkgs [((emacsPackagesFor emacs).emacsWithPackages (epkgs: [epkgs.vterm epkgs.pdf-tools]))])
# TODO: Check what hlissner has enabled
(optionals cfg.doom.enable [
# emacs-all-the-icons-fonts # Needs to be in fonts.fonts
(ripgrep.override {withPCRE2 = true;})
fd
zstd
sqlite # Org roam
inkscape # Org latex preview
graphviz # Org graphviz support
gnuplot # Org gnuplot support
pandoc # Org export formats
maim
bashInteractive # For keychain
# TODO: I don't want to have this here permanently, maybe put in a shell.nix if compilation is needed?
gcc # Need this for org roam
# TODO: Conflicts with global python?
# withPackages expects a function that gets all the packages as argument and returns a list with the packages we want
(python310.withPackages (ppkgs: [ppkgs.pygments])) # Latex minted
# TODO: Does it work like this aswell?
# python310Packages.pygments
# nixfmt # This belongs in specific flake.nix
# shellcheck # This belongs in specific flake.nix
texlive.combined.scheme-full
])
];
home.sessionPath = mkIf cfg.doom.enable ["${config.home.homeDirectory}/.emacs.d/bin"];
# Note: Don't do it this way as the config becomes immutable
# We tell HomeManager where the config files belong
# home.file.".config/doom" = {
# # With onChange you even could rebuild doom emacs when rebuilding HomeManager but I don't want this to become too slow
# recursive = true; # is a directory
# source = ../../config/doom;
# };
home.activation = mkMerge [
# The parantheses around mkIf are needed for precedence in this case
(mkIf cfg.doom.enable {
# If doom is enabled we want to clone the framework
# The activation script is being run when home-manager rebuilds
# Because we write to the filesystem, this script has to be run after HomeManager's writeBoundary
installDoomEmacs = hm.dag.entryAfter ["writeBoundary"] ''
if [ ! -d "${config.home.homeDirectory}/.emacs.d" ]; then
git clone --depth=1 --single-branch "https://github.com/doomemacs/doomemacs" "${config.home.homeDirectory}/.emacs.d"
fi
'';
# With this approach we keep the config mutable as it is not copied and linked from store
linkDoomConfig =
hm.dag.entryAfter ["writeBoundary" "installDoomEmacs"]
(mkLink "${config.home.homeDirectory}/NixFlake/config/doom" "${config.home.homeDirectory}/.config/doom");
})
(mkElse cfg.doom.enable {
unlinkDoomConfig =
hm.dag.entryAfter ["writeBoundary" "installDoomEmacs"]
(mkUnlink "${config.home.homeDirectory}/.config/doom");
})
(mkIf (cfg.doom.enable && cfg.doom.autoSync) {
syncDoomEmacs = hm.dag.entryAfter ["writeBoundary" "linkDoomConfig"] ''
${config.home.homeDirectory}/.emacs.d/bin/doom sync &
'';
})
(mkIf (cfg.doom.enable && cfg.doom.autoUpgrade) {
upgradeDoomEmacs = hm.dag.entryAfter ["writeBoundary" "linkDoomConfig"] ''
${config.home.homeDirectory}/.emacs.d/bin/doom upgrade -!
'';
})
];
};
}

View File

@ -0,0 +1,20 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "Emacs module";
# TODO: Use an enum for this not individual options
nixpkgs = mkBoolOption false "Use Emacs from the official repositories";
nativeComp = mkBoolOption false "Use Emacs 28.x branch with native comp support";
pgtkNativeComp = mkBoolOption false "Use Emacs 29.x branch with native comp and pure gtk support";
doom = {
enable = mkEnableOption "Doom Emacs framework";
autoSync = mkBoolOption false "Sync Doom Emacs on nixos-rebuild";
autoUpgrade = mkBoolOption false "Upgrade Doom Emacs on nixos-rebuild";
};
}

View File

@ -0,0 +1,153 @@
# Example: https://beb.ninja/post/email/
# Example: https://sbr.pm/configurations/mails.html
# TODO: Protonmail-bridge
# TODO: Change to use thunderbird only
# NOTE: The passwords must exist in kwallet
{
config,
nixosConfig,
lib,
mylib,
pkgs,
...
}:
with lib;
with mylib.modules; let
cfg = config.modules.email;
in {
options.modules.email = import ./options.nix {inherit lib mylib;};
# TODO: Add Maildir to nextcloud sync
config = mkIf cfg.enable {
home.packages = with pkgs;
builtins.concatLists [
(optionals cfg.kmail.enable [kmail])
];
home.file = mkMerge [
(optionalAttrs (cfg.kmail.enable && cfg.kmail.autostart) {
".config/autostart/org.kde.kmail2.desktop".source = ../../config/autostart/org.kde.kmail2.desktop;
})
];
programs = {
mbsync.enable = true; # isync package
msmtp.enable = true;
# Run notmuch new to index all new mail
notmuch = {
enable = true;
hooks = {
# When running notmuch new all channels will be syncronized by mbsync
preNew = "mbsync --all";
};
};
};
# TODO: imapnotify can't parse the configuration, HM bug?
services.imapnotify.enable = cfg.imapnotify;
# Autosync, don't need imapnotify when enabled
systemd.user.services.mail-autosync = (mkIf cfg.autosync) {
Unit = {Description = "Automatic notmuch/mbsync synchronization";};
Service = {
Type = "oneshot";
# ExecStart = "${pkgs.isync}/bin/mbsync -a";
ExecStart = "${pkgs.notmuch}/bin/notmuch new";
};
};
systemd.user.timers.mail-autosync = (mkIf cfg.autosync) {
Unit = {Description = "Automatic notmuch/mbsync synchronization";};
Timer = {
OnBootSec = "30";
OnUnitActiveSec = "5m";
};
Install = {WantedBy = ["timers.target"];};
};
accounts.email.accounts = {
urpost = {
address = "tobi@urpost.de";
userName = "tobi@urpost.de";
realName = "Christoph Urlacher";
signature.showSignature = "none";
imap.host = "mail.zeus08.de";
imap.port = 993;
smtp.host = "mail.zeus08.de";
smtp.port = 465;
passwordCommand = "kwallet-query -f email -r urpost kdewallet";
mbsync = {
# Imap
enable = true;
create = "maildir";
};
msmtp.enable = true; # Smtp
notmuch.enable = true;
imapnotify.enable = cfg.imapnotify;
imapnotify.onNotify = {
mail = "${pkgs.notmuch}/bin/notmuch new && ${pkgs.libnotify}/bin/notify-send 'New mail arrived on Urpost'";
};
primary = true;
};
hhu = {
address = "christoph.urlacher@hhu.de";
userName = "churl100";
realName = "Christoph Urlacher";
signature.showSignature = "none";
imap.host = "mail.hhu.de";
imap.port = 993;
smtp.host = "mail.hhu.de";
smtp.port = 465;
passwordCommand = "kwallet-query -f email -r hhu kdewallet";
mbsync = {
# Imap
enable = true;
create = "maildir";
};
msmtp.enable = true; # Smtp
notmuch.enable = true;
imapnotify.enable = cfg.imapnotify;
imapnotify.onNotify = {
mail = "${pkgs.notmuch}/bin/notmuch new && ${pkgs.libnotify}/bin/notify-send 'New mail arrived on HHU'";
};
primary = false;
};
# TODO: Setup the correct groups/patterns
gmail = {
address = "tobiasmustermann529@gmail.com";
userName = "tobiasmustermann529@gmail.com";
realName = "Christoph Urlacher";
signature.showSignature = "none";
flavor = "gmail.com";
# NOTE: Uses Gmail app password
passwordCommand = "kwallet-query -f email -r gmail kdewallet";
mbsync = {
# Imap
enable = true;
create = "maildir";
patterns = ["*" "![Gmail]*" "[Gmail]/Sent Mail" "[Gmail]/Starred" "[Gmail]/All Mail"]; # Only sync inbox
};
msmtp.enable = true; # Smtp
notmuch.enable = true;
imapnotify.enable = cfg.imapnotify;
imapnotify.onNotify = {
mail = "${pkgs.notmuch}/bin/notmuch new && ${pkgs.libnotify}/bin/notify-send 'New mail arrived on GMail'";
};
primary = false;
};
};
};
}

View File

@ -0,0 +1,16 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "Email";
autosync = mkEnableOption "Automatically call \"notmuch new\" via systemd timer";
imapnotify = mkEnableOption "Use imapnotify to sync and index mail automatically";
kmail = {
enable = mkEnableOption "Kmail";
autostart = mkEnableOption "Autostart Kmail";
};
}

View File

@ -0,0 +1,172 @@
{
config,
nixosConfig,
lib,
mylib,
pkgs,
...
}:
with lib;
with mylib.modules;
# NOTE: The module is also used by other modules (gaming, audio).
# It is important that every flatpak interaction is handled through this module
# to prevent that anything is removed by a module although it is required by another one
let
cfg = config.modules.flatpak;
in {
options.modules.flatpak = import ./options.nix {inherit lib mylib;};
config = mkIf cfg.enable {
assertions = [
{
assertion = nixosConfig.services.flatpak.enable;
message = "Cannot use the flatpak module with flatpak disabled in nixos!";
}
];
# NOTE: Is already set by flatpak.enable in configuration.nix
# xdg.systemDirs.data = [
# "/var/lib/flatpak/exports/share"
# "${home.homeDirectory}/.local/share/flatpak/exports/share"
# ];
# TODO: Currently it is not possible to define overrides for the same flatpak from different places
# TODO: Also only filesystem overrides are applied
home.file = let
# Specific overrides
# This generates the set { "<filename>" = "<overrides>"; }
concat_override = name: value: (optionalAttrs (name != null) {".local/share/flatpak/overrides/${name}".text = "[Context]\nfilesystems=${value}";});
# This is a list of sets: [ { "<filename>" = "<overrides>"; } { "<filename>" = "<overrides>"; } ]
extra_overrides = map (set: concat_override (attrName set) (attrValue set)) cfg.extraOverride;
# Global overrides
global_default_overrides = [
"/nix/store:ro"
# TODO: There are irregular problems with flatpak app font antialiasing, I don't know where it comes from or when
# Also some icons are missing, even when icon dir is accessible
# I remember I did something one time that fixed it, but what was it :(?
# NOTE: This doesn't help sadly, also steam can't launch with this because it wants to create a link to ~/.local/share/fonts?
# "${config.home.homeDirectory}/.local/share/icons"
# "${config.home.homeDirectory}/.local/share/fonts"
# TODO: These are not necessary (Really?)
# Make sure flatpaks are allowed to use the icons/fonts that are symlinked by icon/font fix
# "/run/current-system/sw/share/X11/fonts:ro"
# "/run/current-system/sw/share/icons:ro"
];
global_overrides = builtins.concatLists [global_default_overrides cfg.extraGlobalOverride];
str_global_overrides = builtins.concatStringsSep ";" global_overrides;
in
mkMerge ([
{
".local/share/flatpak/overrides/global".text = "[Context]\nfilesystems=${str_global_overrides}";
}
]
++ extra_overrides);
home.activation = mkMerge [
# TODO: Linking isn't always enough, some fonts should be copied aswell...
# We link like this to be able to address the absolute location, also the fonts won't get copied to store
# NOTE: This path contains all the fonts because fonts.fontDir.enable is true
(mkIf cfg.fontFix {
linkFontDir =
lib.hm.dag.entryAfter ["writeBoundary"]
(mkLink "/run/current-system/sw/share/X11/fonts" "${config.home.homeDirectory}/.local/share/fonts/fonts");
copyBaseFonts = lib.hm.dag.entryAfter ["writeBoundary"] ''
cp -f ${pkgs.lxgw-wenkai}/share/fonts/truetype/LXGWWenKaiMono-Regular.ttf ${config.home.homeDirectory}/.local/share/fonts/
cp -f ${pkgs.nerdfonts.override {fonts = ["JetBrainsMono"];}}/share/fonts/truetype/NerdFonts/JetBrainsMonoNerdFontMono-Regular.ttf ${config.home.homeDirectory}/.local/share/fonts/
cp -f ${pkgs.noto-fonts}/share/fonts/noto/NotoSans[wdth,wght].ttf ${config.home.homeDirectory}/.local/share/fonts/
cp -f ${pkgs.noto-fonts-color-emoji}/share/fonts/noto/NotoColorEmoji.ttf ${config.home.homeDirectory}/.local/share/fonts/
'';
})
(mkElse cfg.fontFix {
unlinkFontDir =
lib.hm.dag.entryAfter ["writeBoundary"]
(mkUnlink "${config.home.homeDirectory}/.local/share/fonts/fonts");
deleteBaseFonts = lib.hm.dag.entryAfter ["writeBoundary"] ''
rm ${config.home.homeDirectory}/.local/share/fonts/LXGWWenKaiMono-Regular.ttf
rm ${config.home.homeDirectory}/.local/share/fonts/JetBrainsMonoNerdFontMono-Regular.ttf
rm ${config.home.homeDirectory}/.local/share/fonts/NotoSans[wdth,wght].ttf
rm ${config.home.homeDirectory}/.local/share/fonts/NotoColorEmoji.ttf
'';
})
# Fixes missing icons + cursor
# NOTE: This path works because we have homeManager.useUserPackages = true (everything is stored in /etc/profiles/)
(mkIf cfg.iconFix {
linkIconDir =
lib.hm.dag.entryAfter ["writeBoundary"]
(mkLink "/etc/profiles/per-user/christoph/share/icons" "${config.home.homeDirectory}/.local/share/icons");
})
(mkElse cfg.iconFix {
unlinkIconDir =
lib.hm.dag.entryAfter ["writeBoundary"]
(mkUnlink "${config.home.homeDirectory}/.local/share/icons");
})
# TODO: I should find a smarter way than this to make it easy to add flatpak options
{
# TODO: Enable this block only if any flatpak is enabled
installFlatpaks = let
to_install = builtins.concatLists [
(optionals cfg.discord.enable ["com.discordapp.Discord"])
(optionals cfg.spotify.enable ["com.spotify.Client"])
(optionals cfg.flatseal.enable ["com.github.tchx84.Flatseal"])
(optionals cfg.bottles.enable ["com.usebottles.bottles"])
(optionals cfg.obsidian.enable ["md.obsidian.Obsidian"])
(optionals cfg.jabref.enable ["org.jabref.Jabref"])
cfg.extraInstall
];
to_install_str = builtins.concatStringsSep " " to_install;
in
# Flatpak install can take a long time so we disconnect the process to not trigger the HM timeout (90s)
lib.hm.dag.entryAfter ["writeBoundary"] ''
sudo flatpak install -y ${to_install_str} &
'';
}
{
# TODO: Enable this block only if any flatpak is disabled
removeFlatpaks = let
to_remove = builtins.concatLists [
(optionals (!cfg.discord.enable) ["com.discordapp.Discord"])
(optionals (!cfg.spotify.enable) ["com.spotify.Client"])
(optionals (!cfg.flatseal.enable) ["com.github.tchx84.Flatseal"])
(optionals (!cfg.bottles.enable) ["com.usebottles.bottles"])
(optionals (!cfg.obsidian.enable) ["md.obsidian.Obsidian"])
(optionals (!cfg.jabref.enable) ["org.jabref.Jabref"])
# Remove only the flatpaks that are not present in extraInstall
(without cfg.extraRemove cfg.extraInstall)
];
to_remove_str = builtins.concatStringsSep " " to_remove;
in
# By using || we make sure this command never throws any errors
# Uninstallation is fast so HM timeout shouldn't be triggered
lib.hm.dag.entryAfter ["writeBoundary"] ''
sudo flatpak uninstall -y ${to_remove_str} || echo "Nothing to be removed"
'';
}
(mkIf cfg.autoUpdate {
# Flatpak install can take a long time so we disconnect the process to not trigger the HM timeout (90s)
updateFlatpak = lib.hm.dag.entryAfter ["writeBoundary"] ''
sudo flatpak update -y &
'';
})
# Execute this after flatpak removal as there can be leftovers
(mkIf cfg.autoPrune {
pruneFlatpak = lib.hm.dag.entryAfter ["writeBoundary" "removeFlatpak"] ''
sudo flatpak uninstall --unused -y
'';
})
];
};
}

View File

@ -0,0 +1,55 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "Flatpak module";
fontFix = mkBoolOption true "Link fonts to ~/.local/share/fonts so flatpak apps can find them";
iconFix = mkBoolOption true "Link icons to ~/.local/share/icons so flatpak apps can find them";
autoUpdate = mkBoolOption false "Update flatpak apps on nixos-rebuild";
autoPrune = mkBoolOption false "Remove unused packages on nixos-rebuild";
# TODO: Add library function to make this easier
# TODO: The flatpak name should be included and a list of all enabled apps should be available
# TODO: Do this for strings + packages
discord.enable = mkEnableOption "Discord";
spotify.enable = mkEnableOption "Spotify";
flatseal.enable = mkEnableOption "Flatseal";
bottles.enable = mkEnableOption "Bottles";
obsidian.enable = mkEnableOption "Obsidian";
jabref.enable = mkEnableOption "Jabref";
# xwaylandvideobridge = mkEnableOption "XWayland Video Bridge"; # TODO
# TODO: Can I use extraInstall = { "com.valve.Steam" = true/false; } and pass the module option as value?
# This is mainly used by other modules to allow them to use flatpak packages
extraInstall = mkOption {
type = types.listOf types.str;
default = [];
description = "Flatpaks that will be installed additionally";
};
# This doesn't uninstall if any flatpak is still present in the extraInstall list
extraRemove = mkOption {
type = types.listOf types.str;
default = [];
description = "Flatpaks that will be removed additionally (use with extraInstall)";
};
extraOverride = mkOption {
type = types.listOf types.attrs;
default = [];
# TODO: Change the format to { "com.usebottles.bottles" = [ "~/Documents" "~/Downloads" ]; }
# TODO: This requires that the lists of the same key are being merged recursively, mkMerge would override the key
example = [{"com.usebottles.bottles" = "\${config.home.homeDirectory}/Documents";}];
description = "Additional overrides";
};
extraGlobalOverride = mkOption {
type = types.listOf types.str;
default = [];
example = ["\${config.home.homeDirectory}/Documents:ro"];
description = "Additional global overrides";
};
}

View File

@ -0,0 +1,161 @@
{
config,
lib,
mylib,
pkgs,
...
}:
with lib;
with mylib.modules; let
cfg = config.modules.gaming;
cfgfp = config.modules.flatpak;
in {
imports = [
# NOTE: I don't know if this is the right approach or if I should use config.modules.flatpak
../flatpak
];
# TODO: Enable flatpak MangoHud, there are multiple versions, Steam.Utility.MangoHud works but can't be configured (in ~/.config/MangoHud), other versions don't even work (need to figure that out as Steam.Utility.MangoHud is EOL...)
# TODO: SteamTinkerLaunch option
# TODO: Dolphin + SteamRomManager option
options.modules.gaming = import ./options.nix {inherit lib mylib;};
config = mkIf cfg.enable {
assertions = [
# TODO: Make lib function for multiple assertions that have the same condition
(mkIf cfg.steam.enable {
assertion = cfgfp.enable;
message = "Cannot enable Steam without the flatpak module!";
})
(mkIf cfg.prism.enable {
assertion = cfgfp.enable;
message = "Cannot enable PrismLauncher without the flatpak module!";
})
(mkIf cfg.bottles.enable {
assertion = cfgfp.enable;
message = "Cannot enable Bottles without the flatpak module!";
})
];
home.packages = with pkgs;
builtins.concatLists [
[
gamemode # gamemode should be always enabled (could also be enabled by audio module)
oversteer # TODO: Make option
# Sometimes needed for Proton prefix shenenigans (for AC etc.), but probably only works with Protontricks only so disable for now...
# wine64 # TODO: Make option or dependant on protontricks?
]
# TODO: Extra config (extensions etc) in chromium module
# (optionals cfg.discordChromium.enable [chromium])
# Prefer flatpak version as nixpkgs version isn't always updated in time
# (optionals cfg.discordElectron.enable [discord])
(optionals cfg.steam.adwaita [adwaita-for-steam])
# Prefer flatpak version as this one doesn't find the STEAM_DIR automatically
# (optionals cfg.steam.enable [ protontricks ])
# (optionals cfg.dwarffortress.enable [dwarf-fortress-packages.dwarf-fortress-full])
(optionals cfg.cemu.enable [cemu cdecrypt wiiu-downloader])
];
# This doesn't work because steam doesn't detect symlinked skins, files have to be copied
# https://github.com/ValveSoftware/steam-for-linux/issues/3572
# home.file = mkMerge [
# (optionalAttrs cfg.steam.adwaita {
# "adwaita-for-steam" = {
# source = "${pkgs.adwaita-for-steam}/share/adwaita-for-steam/Adwaita";
# target = ".var/app/com.valvesoftware.Steam/.local/share/Steam/skins/Adwaita";
# recursive = false;
# };
# })
# ];
home.activation = mkMerge [
(optionalAttrs cfg.steam.adwaita {
copySteamAdwaitaSkin = hm.dag.entryAfter ["writeBoundary"] ''
if [ ! -d ${config.home.homeDirectory}/.var/app/com.valvesoftware.Steam/.local/share/Steam/skins ]; then
mkdir ${config.home.homeDirectory}/.var/app/com.valvesoftware.Steam/.local/share/Steam/skins
fi
# Delete the directory to copy again, if src was updated
if [ -d ${config.home.homeDirectory}/.var/app/com.valvesoftware.Steam/.local/share/Steam/skins/Adwaita ]; then
rm -rf ${config.home.homeDirectory}/.var/app/com.valvesoftware.Steam/.local/share/Steam/skins/Adwaita
fi
cp -r ${pkgs.adwaita-for-steam}/share/adwaita-for-steam/Adwaita ${config.home.homeDirectory}/.var/app/com.valvesoftware.Steam/.local/share/Steam/skins/Adwaita
chmod -R +w ${config.home.homeDirectory}/.var/app/com.valvesoftware.Steam/.local/share/Steam/skins/Adwaita
'';
})
(optionalAttrs (! cfg.steam.adwaita) {
deleteSteamAdwaitaSkin = hm.dag.entryAfter ["writeBoundary"] ''
rm -rf ${config.home.homeDirectory}/.var/app/com.valvesoftware.Steam/.local/share/Steam/skins/Adwaita
'';
})
];
# xdg.desktopEntries.discordChromium = mkIf cfg.discordChromium.enable {
# name = "Discord (Chromium)";
# genericName = "Online voice chat";
# icon = "discord";
# exec = "chromium --new-window discord.com/app";
# terminal = false;
# categories = ["Network" "Chat"];
# };
# TODO: Remove the bottles option from the gaming module (move it to the flatpak module)
# NOTE: Important to not disable this option if another module enables it
# modules.flatpak.bottles.enable = mkIf cfg.bottles.enable true;
modules.flatpak.extraOverride = [
# Allow Bottles to manage proton prefixes
(optionalAttrs cfg.bottles.enable {
"com.usebottles.bottles" = "${config.home.homeDirectory}/.var/app/com.valvesoftware.Steam;${config.home.homeDirectory}/GameSSD;${config.home.homeDirectory}/GameHDD";
})
# Allow Steam to access different library folders
# Allow Steam to explicitly run something through ProtonGE
(optionalAttrs cfg.steam.enable {
# TODO: Make the second string into a list [ ~/GameSSD ~/GameHDD ] etc.
"com.valvesoftware.Steam" = "${config.home.homeDirectory}/GameSSD;${config.home.homeDirectory}/GameHDD;/var/lib/flatpak/runtime/com.valvesoftware.Steam.CompatibilityTool.Proton-GE";
})
# Allow protontricks to change prefixes in different library folders
(optionalAttrs cfg.steam.enable {
"com.github.Matoking.protontricks" = "${config.home.homeDirectory}/GameSSD;${config.home.homeDirectory}/GameHDD";
})
# Allow ProtonUP-Qt to see game list and access steam
(optionalAttrs (cfg.steam.enable && cfg.steam.protonup) {
"net.davidotek.pupgui2" = "${config.home.homeDirectory}/.var/app/com.valvesoftware.Steam;${config.home.homeDirectory}/GameSSD;${config.home.homeDirectory}/GameHDD";
})
];
# TODO: RetroArch option org.libretro.RetroArch
modules.flatpak.extraInstall = builtins.concatLists [
(optionals cfg.steam.enable [
"com.valvesoftware.Steam"
"com.github.Matoking.protontricks"
# "com.valvesoftware.Steam.Utility.steamtinkerlaunch"
# "com.steamgriddb.steam-rom-manager"
# "org.DolphinEmu.dolphin-emu"
])
(optionals (cfg.steam.enable && cfg.steam.gamescope) ["com.valvesoftware.Steam.Utility.gamescope"])
(optionals (cfg.steam.enable && cfg.steam.protonup) ["net.davidotek.pupgui2"])
(optionals cfg.prism.enable ["org.prismlauncher.PrismLauncher"])
];
modules.flatpak.extraRemove = builtins.concatLists [
(optionals (!cfg.steam.enable) [
"com.valvesoftware.Steam"
"com.github.Matoking.protontricks"
# "com.valvesoftware.Steam.Utility.steamtinkerlaunch"
# "com.steamgriddb.steam-rom-manager"
# "org.DolphinEmu.dolphin-emu"
])
(optionals (!cfg.steam.enable || !cfg.steam.gamescope) ["com.valvesoftware.Steam.Utility.gamescope"])
(optionals (!cfg.steam.enable || !cfg.steam.protonup) ["net.davidotek.pupgui2"])
(optionals (!cfg.prism.enable) ["org.prismlauncher.PrismLauncher"])
];
};
}

View File

@ -0,0 +1,23 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "Gaming module";
# discordElectron.enable = mkEnableOption "Discord (Electron) (nixpkgs)";
# discordChromium.enable = mkEnableOption "Discord (Chromium)";
prism.enable = mkEnableOption "PrismLauncher for Minecraft (flatpak)";
bottles.enable = mkEnableOption "Bottles (flatpak)";
# dwarffortress.enable = mkEnableOption "Dwarf Fortress";
cemu.enable = mkEnableOption "Cemu (nixpkgs)";
steam = {
enable = mkEnableOption "Steam (flatpak)";
gamescope = mkBoolOption false "Enable the gamescope micro compositor (flatpak)";
adwaita = mkBoolOption false "Enable the adwaita-for-steam skin";
protonup = mkBoolOption false "Enable ProtonUP-QT";
};
}

View File

@ -0,0 +1,64 @@
# TODO: Expose some settings
# TODO: Fix language config
{
config,
nixosConfig,
lib,
mylib,
pkgs,
...
}:
with lib;
with mylib.modules; let
cfg = config.modules.helix;
in {
options.modules.helix = import ./options.nix {inherit lib mylib;};
config = mkIf cfg.enable {
home.sessionVariables = {
EDITOR = "hx";
VISUAL = "hx";
};
programs.helix = {
enable = true;
# NOTE: Syntax changed
# languages = [
# {
# name = "verilog";
# roots = [
# ".svls.toml"
# ".svlint.toml"
# ];
# language-server = {
# command = "svls";
# args = [];
# };
# }
# ];
# https://docs.helix-editor.com/configuration.html
settings = {
theme = "catppuccin_latte";
editor = {
scrolloff = 10;
mouse = false; # Default true
middle-click-paste = false; # Default true
line-number = "relative";
cursorline = true;
color-modes = true;
auto-completion = true; # Default
bufferline = "multiple";
cursor-shape = {
normal = "block";
insert = "bar";
select = "underline";
};
lsp.display-messages = true;
indent-guides.render = false;
};
};
};
};
}

View File

@ -0,0 +1,9 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "Helix Editor";
}

View File

@ -0,0 +1,64 @@
{
config,
nixosConfig,
lib,
mylib,
pkgs,
...
}:
# TODO: Remove this module, put protonmail into the email module
with lib;
with mylib.modules; let
cfg = config.modules.misc;
in {
options.modules.misc = import ./options.nix {inherit lib mylib;};
config = mkIf cfg.enable {
home.packages = with pkgs;
builtins.concatLists [
(optionals cfg.keepass.enable [keepassxc])
(optionals cfg.protonmail.enable [protonmail-bridge])
];
systemd.user.services = mkMerge [
(optionalAttrs (cfg.keepass.enable && cfg.keepass.autostart) {
# TODO: Disable only for plasma
# autostart-keepass = {
# Unit = {
# Type = "oneshot";
# Description = "KeePassXC password manager";
# PartOf = [ "graphical-session.target" ];
# After = [ "graphical-session.target" ];
# };
# Service = {
# # Environment = "PATH=${config.home.profileDirectory}/bin"; # Leads to /etc/profiles/per-user/christoph/bin
# ExecStart = "${pkgs.keepassxc}/bin/keepassxc ${config.home.homeDirectory}/Documents/KeePass/passwords.kbdx";
# # ExecStop = "${pkgs.noisetorch}/bin/noisetorch -u";
# Restart = "on-failure";
# };
# Install.WantedBy = [ "graphical-session.target" ];
# };
})
# TODO: Disable only for plasma
# TODO: Error: has no wallet, find out how to get imap credentials from this
# (optionalAttrs (cfg.protonmail.enable && cfg.protonmail.autostart) {
# autostart-protonmail = {
# Unit = {
# Description = "ProtonMail Bridge";
# After = [ "network.target" ];
# };
# Service = {
# ExecStart = "${pkgs.protonmail-bridge}/bin/protonmail-bridge --no-window --log-level info --noninteractive";
# Restart = "always";
# };
# Install.WantedBy = [ "default.target" ];
# };
# })
];
};
}

View File

@ -0,0 +1,19 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "Misc module";
keepass = {
enable = mkEnableOption "KeePassXC";
autostart = mkBoolOption false "Autostart KeePassXC";
};
protonmail = {
enable = mkEnableOption "ProtonMail";
autostart = mkBoolOption false "Autostart ProtonMail Bridge";
};
}

View File

@ -0,0 +1,50 @@
# Changed from https://github.com/nix-community/home-manager/blob/master/modules/services/nextcloud-client.nix
# I use this instead of the HM module as the autostart wasn't working there
# TODO: Remove this module
# TODO: Check the HM module again if anything changed, as this has also stopped working
# Nextcloud immediately crashes on start, autostart isn't working either...
{
config,
lib,
mylib,
pkgs,
...
}:
with lib;
with mylib.modules; let
cfg = config.modules.nextcloud;
in {
options.modules.nextcloud = import ./options.nix {inherit lib mylib;};
config = mkIf cfg.enable {
assertions = [
{
assertion = !config.services.nextcloud-client.enable;
message = "Can't enable both HM nextcloud and my nextcloud module!";
}
];
# I want to have nextcloud-client in the path when the module is enabled
home.packages = with pkgs; [nextcloud-client];
# TODO: Disable only for plasma
# systemd.user.services = (mkIf cfg.autostart) {
# autostart-nextcloud-client = {
# Unit = {
# Description = "Nextcloud Client";
# PartOf = [ "graphical-session.target" ];
# # was graphical-session-pre.target originally in HM
# After = [ "graphical-session.target" "network-online.target" ];
# };
# Service = {
# Environment = "PATH=${config.home.profileDirectory}/bin";
# ExecStart = "${pkgs.nextcloud-client}/bin/nextcloud --background";
# };
# Install.WantedBy = [ "graphical-session.target" ];
# };
# };
};
}

View File

@ -0,0 +1,10 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "Nextcloud Client";
autostart = mkBoolOption false "Autostart the Nextcloud client (systemd)";
}

View File

@ -0,0 +1,81 @@
{
config,
nixosConfig,
lib,
mylib,
pkgs,
...
}:
with lib;
with mylib.modules; let
cfg = config.modules.ranger;
in {
options.modules.ranger = import ./options.nix {inherit lib mylib;};
config = mkIf cfg.enable {
home.packages = with pkgs;
lib.concatLists [
[
ranger
atool
p7zip
zip
unzip
unrar
libarchive
exiftool
mediainfo
]
(optionals cfg.preview [
# ueberzug # Only X11
# TODO: Conflicts with global python?
python310Packages.pillow
ffmpegthumbnailer
imagemagick
poppler-utils
])
];
home.file = mkMerge [
{
".config/ranger/rc.conf".text = let
# TODO: Why does mkMerge don't work here?
settings =
{
column_ratios = "1,1";
vcs_aware = "true";
preview_images_method = "kitty"; # TODO: Only if kitty enabled
unicode_ellipsis = "true";
draw_borders =
if cfg.preview
then "none"
else "both"; # doesn't work well with preview
line_numbers = "relative";
preview_images =
if cfg.preview
then "true"
else "false";
use_preview_script =
if cfg.preview
then "true"
else "false";
}
// (optionalAttrs cfg.preview {
preview_script = "${config.home.homeDirectory}/.config/ranger/scope.sh";
});
# The settings { column_ratios = "1,1"; } get turned into { column_ratios = "set column_ratios = 1,1"; }
settings_in_values = mapAttrs (name: value: concatStringsSep " " ["set" name value]) settings;
settings_list = attrValues settings_in_values; # Results in [ "set column_rations = 1,1" ]
settings_str = concatStringsSep "\n" settings_list;
in
settings_str;
}
(optionalAttrs cfg.preview {
".config/ranger/scope.sh".source = ../../config/ranger/scope.sh;
})
];
};
}

View File

@ -0,0 +1,10 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "Ranger";
preview = mkBoolOption false "Enable Ranger image preview";
}

View File

@ -0,0 +1,156 @@
# TODO: Expose some settings
{
config,
nixosConfig,
lib,
mylib,
pkgs,
...
}:
with lib;
with mylib.modules; let
cfg = config.modules.vscode;
in {
options.modules.vscode = import ./options.nix {inherit lib mylib;};
config = mkIf cfg.enable {
programs.vscode = {
enable = true;
enableExtensionUpdateCheck = false;
enableUpdateCheck = false;
extensions = with pkgs.vscode-extensions; [
# alefragnani.bookmarks # TODO: Use inline bookmarks instead
# alefragnani.project-manager # NOTE: Not much sense with flake dev environments
catppuccin.catppuccin-vsc
catppuccin.catppuccin-vsc-icons
christian-kohler.path-intellisense
# codezombiech.gitignore # NOTE: Superfluous
# coolbear.systemd-unit-file # NOTE: Unnecessary on NixOS
eamodio.gitlens
# formulahendry.auto-rename-tag
# formulahendry.auto-close-tag
# gitlab.gitlab-workflow
# irongeek.vscode-env
# jnoortheen.nix-ide
# kamadorueda.alejandra
# kamikillerto.vscode-colorize
# llvm-vs-code-extensions.vscode-clangd
# matklad.rust-analyzer
mechatroner.rainbow-csv
# mikestead.dotenv
# mkhl.direnv
# ms-azuretools.vscode-docker
# ms-kubernetes-tools.vscode-kubernetes-tools
ms-python.python
ms-toolsai.jupyter
ms-vscode.cmake-tools
ms-vscode.cpptools
# ms-vscode.hexeditor
# ms-vscode.makefile-tools
ms-python.black-formatter
ms-python.vscode-pylance
ms-vscode-remote.remote-ssh
# naumovs.color-highlight
njpwerner.autodocstring
# james-yu.latex-workshop
# redhat.java
# redhat.vscode-xml
# redhat.vscode-yaml
ritwickdey.liveserver
# rubymaniac.vscode-paste-and-indent
ryu1kn.partial-diff
# serayuzgur.crates
shd101wyy.markdown-preview-enhanced
# skyapps.fish-vscode
# tamasfe.even-better-toml
# timonwong.shellcheck
# tomoki1207.pdf # Incompatible with latex workshop
# valentjn.vscode-ltex
vscodevim.vim
vscode-icons-team.vscode-icons
# yzhang.markdown-all-in-one
];
# haskell = {};
# keybindings = {};
userSettings = {
# VSCode Internals
"editor.fontFamily" = "JetBrainsMono Nerd Font Mono";
"editor.fontSize" = 16;
"editor.renderWhitespace" = "selection";
"editor.cursorStyle" = "line"; # Use line for vim plugin
"editor.lineNumbers" = "relative";
"editor.linkedEditing" = true;
"editor.smoothScrolling" = true;
"editor.stickyScroll.enabled" = true;
"editor.tabCompletion" = "on";
"editor.cursorSmoothCaretAnimation" = "on";
"editor.cursorSurroundingLines" = 10;
"editor.minimap.renderCharacters" = false;
"editor.bracketPairColorization.enabled" = true;
"editor.guides.bracketPairs" = "active";
"editor.guides.bracketPairsHorizontal" = "active";
"editor.guides.highlightActiveIndentation" = false;
"files.autoSave" = "onFocusChange";
"files.trimFinalNewlines" = true;
"files.trimTrailingWhitespace" = true; # NOTE: If this is enabled with frequent autosave, the current lines whitespace will always be removed, which is obnoxious
"window.restoreWindows" = "none";
"window.titleBarStyle" = "custom"; # NOTE: Should help with crashing on wayland
# "window.titleBarStyle" = "native";
# "window.menuBarVisibility" = "toggle";
"workbench.enableExperiments" = false;
"workbench.list.smoothScrolling" = true;
# "workbench.colorTheme" = "Default Light Modern";
# "workbench.iconTheme" = "vscode-icons";
"workbench.colorTheme" = "Catppuccin Latte";
"workbench.iconTheme" = "catppuccin-latte";
"remote.SSH.configFile" = "~/.ssh/custom-config";
"security.workspace.trust.enabled" = false;
# Language Tool
"ltex.checkFrequency" = "manual";
# LaTeX
"latex-workshop.latex.tools" = [
{
"name" = "latexmk";
"command" = "latexmk";
"args" = [
"-synctex=1"
"-shell-escape"
"-interaction=nonstopmode"
"-file-line-error"
"-pdf"
"-outdir=%OUTDIR%"
"%DOC%"
];
"env" = {};
}
];
"latex-workshop.latexindent.args" = [
"-c"
"%DIR%/"
"%TMPFILE%"
"-m"
"-y=defaultIndent: '%INDENT%'"
];
# Nix
"[nix]"."editor.tabSize" = 2;
"nix.enableLanguageServer" = true;
"nix.serverPath" = "nil";
"nix.formatterPath" = "alejandra";
# C++
# "C_Cpp.intelliSenseEngine" = "disabled"; # IntelliSense conflics with Clangd
};
# TODO: Snippets
};
};
}

View File

@ -0,0 +1,9 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "Visual Studio Code";
}

View File

@ -0,0 +1,85 @@
{
config,
nixosConfig,
lib,
mylib,
pkgs,
...
}: let
inherit (config.modules) beets;
in {
options.modules.beets = import ./options.nix {inherit lib mylib;};
config = lib.mkIf beets.enable {
programs.beets = {
enable = true;
mpdIntegration = {
host = "127.0.0.1";
port = config.services.mpd.network.port;
enableUpdate = true;
enableStats = true;
};
# https://beets.readthedocs.io/en/stable/reference/config.html
settings = {
directory = "${config.home.homeDirectory}/Music";
library = "${config.home.homeDirectory}/Music/.beets/library.db";
threaded = true;
art_filename = "cover";
ui = {
color = true;
};
import = {
write = true; # Write metadata to files
copy = false; # Copy files to the music directory when importing
move = true; # Move files to the music directory when importing
log = "${config.home.homeDirectory}/Music/.beetslog.txt";
};
paths = {
default = "$albumartist/$albumartist - $album/$track $title";
singleton = "0 Singles/$artist - $title"; # Single songs
comp = "1 Various/$album/$track $title";
};
plugins = [
"badfiles" # check audio file integrity
"duplicates"
"edit" # edit metadata in text editor
"fetchart" # pickup local cover art or search online
"fish" # beet fish generates ~/.config/fish/completions file
# "lyrics" # fetch song lyrics
"musicbrainz" # auto tagger data source
"replaygain" # write replaygain tags for automatic loudness adjustments
];
fetchart = {
auto = "yes";
sources = "filesystem coverart itunes amazon albumart"; # sources are queried in this order
};
# lyrics = {
# auto = "yes"; # only embeds lyrics into metadata, needed for jellyfin but useless for rmpc
# synced = "yes"; # prefer synced lyrics if provided
# };
replaygain = {
auto = "yes"; # analyze on import automatically
backend = "ffmpeg";
overwrite = true; # re-analyze files with existing replaygain tags on import
};
};
};
# Generate fish completions
# TODO: This doesn't work if ~/Music is mounted after the activation...
# home.activation = {
# beets-fish-completions = lib.hm.dag.entryAfter ["writeBoundary"] ''
# echo "Generating beet completions for fish shell at ~/.config/fish/completions/beet.fish"
# beet fish
# '';
# };
};
}

View File

@ -0,0 +1,7 @@
{
lib,
mylib,
...
}: {
enable = lib.mkEnableOption "Enable the beet music library tagger";
}

View File

@ -0,0 +1,209 @@
{
config,
nixosConfig,
lib,
mylib,
pkgs,
...
}: let
inherit (config.modules) btop color;
in {
options.modules.btop = import ./options.nix {inherit lib mylib;};
config = lib.mkIf btop.enable {
programs.btop = {
enable = true;
package =
if btop.cuda
then pkgs.btop-cuda
else pkgs.btop;
themes = {
# https://github.com/catppuccin/btop/tree/main
system-theme = ''
# Main background, empty for terminal default, need to be empty if you want transparent background
theme[main_bg]=${color.hexS.base}
# Main text color
theme[main_fg]=${color.hexS.text}
# Title color for boxes
theme[title]=${color.hexS.text}
# Highlight color for keyboard shortcuts
theme[hi_fg]=${color.hexS.accent}
# Background color of selected item in processes box
theme[selected_bg]=${color.hexS.accentDim}
# Foreground color of selected item in processes box
theme[selected_fg]=${color.hexS.accentText}
# Color of inactive/disabled text
theme[inactive_fg]=${color.hexS.overlay0}
# Color of text appearing on top of graphs, i.e uptime and current network graph scaling
theme[graph_text]=${color.hexS.overlay0}
# Background color of the percentage meters
theme[meter_bg]=${color.hexS.surface1}
# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
theme[proc_misc]=${color.hexS.rosewater}
# CPU, Memory, Network, Proc box outline colors
theme[cpu_box]=${color.hexS.mauve} #Mauve
theme[mem_box]=${color.hexS.green} #Green
theme[net_box]=${color.hexS.maroon} #Maroon
theme[proc_box]=${color.hexS.blue} #Blue
# Box divider line and small boxes line color
theme[div_line]=${color.hexS.overlay0}
# Temperature graph color (Green -> Yellow -> Red)
theme[temp_start]=${color.hexS.green}
theme[temp_mid]=${color.hexS.yellow}
theme[temp_end]=${color.hexS.red}
# CPU graph colors (Teal -> Lavender)
theme[cpu_start]=${color.hexS.teal}
theme[cpu_mid]=${color.hexS.sapphire}
theme[cpu_end]=${color.hexS.lavender}
# Mem/Disk free meter (Mauve -> Lavender -> Blue)
theme[free_start]=${color.hexS.mauve}
theme[free_mid]=${color.hexS.lavender}
theme[free_end]=${color.hexS.blue}
# Mem/Disk cached meter (Sapphire -> Lavender)
theme[cached_start]=${color.hexS.sapphire}
theme[cached_mid]=${color.hexS.blue}
theme[cached_end]=${color.hexS.lavender}
# Mem/Disk available meter (Peach -> Red)
theme[available_start]=${color.hexS.peach}
theme[available_mid]=${color.hexS.maroon}
theme[available_end]=${color.hexS.red}
# Mem/Disk used meter (Green -> Sky)
theme[used_start]=${color.hexS.green}
theme[used_mid]=${color.hexS.teal}
theme[used_end]=${color.hexS.sky}
# Download graph colors (Peach -> Red)
theme[download_start]=${color.hexS.peach}
theme[download_mid]=${color.hexS.maroon}
theme[download_end]=${color.hexS.red}
# Upload graph colors (Green -> Sky)
theme[upload_start]=${color.hexS.green}
theme[upload_mid]=${color.hexS.teal}
theme[upload_end]=${color.hexS.sky}
# Process box color gradient for threads, mem and cpu usage (Sapphire -> Mauve)
theme[process_start]=${color.hexS.sapphire}
theme[process_mid]=${color.hexS.lavender}
theme[process_end]=${color.hexS.mauve}
'';
};
settings = {
color_theme = "system-theme";
truecolor = true;
vim_keys = true;
rounded_corners = true;
graph_symbol = "braille";
shown_boxes = "cpu gpu0 mem net proc";
update_ms = 1000;
proc_sorting = "memory";
proc_tree = true;
proc_mem_bytes = true;
proc_cpu_graphs = true;
#* Use /proc/[pid]/smaps for memory information in the process info box (very slow but more accurate)
proc_info_smaps = false;
#* In tree-view, always accumulate child process resources in the parent process.
proc_aggregate = true;
#* Sets the CPU stat shown in upper half of the CPU graph, "total" is always available.
#* Select from a list of detected attributes from the options menu.
cpu_graph_upper = "user";
#* Sets the CPU stat shown in lower half of the CPU graph, "total" is always available.
#* Select from a list of detected attributes from the options menu.
cpu_graph_lower = "system";
#* If gpu info should be shown in the cpu box. Available values = "Auto", "On" and "Off".
show_gpu_info = "Off";
show_uptime = true;
check_temp = true; # Show cpu temperature
show_coretemp = true;
#* Set a custom mapping between core and coretemp, can be needed on certain cpus to get correct temperature for correct core.
#* Use lm-sensors or similar to see which cores are reporting temperatures on your machine.
#* Format "x:y" x=core with wrong temp, y=core with correct temp, use space as separator between multiple entries.
#* Example: "4:0 5:1 6:3"
cpu_core_map = "";
temp_scale = "celsius";
base_10_sizes = false;
show_cpu_freq = true;
#* Draw a clock at top of screen, formatting according to strftime, empty string to disable.
#* Special formatting: /host = hostname | /user = username | /uptime = system uptime
clock_format = "%X";
#* Optional filter for shown disks, should be full path of a mountpoint, separate multiple values with whitespace " ".
#* Begin line with "exclude=" to change to exclude filter, otherwise defaults to "most include" filter. Example: disks_filter="exclude=/boot /home/user".
disks_filter = "";
#* Show graphs instead of meters for memory values.
mem_graphs = true;
#* If swap memory should be shown in memory box.
show_swap = true;
#* Show swap as a disk, ignores show_swap value above, inserts itself after first disk.
swap_disk = false;
#* If mem box should be split to also show disks info.
show_disks = true;
#* Filter out non physical disks. Set this to False to include network disks, RAM disks and similar.
only_physical = true;
#* Read disks list from /etc/fstab. This also disables only_physical.
use_fstab = true;
#* Toggles if io activity % (disk busy time) should be shown in regular disk usage view.
show_io_stat = true;
#* Use network graphs auto rescaling mode, ignores any values set above and rescales down to 10 Kibibytes at the lowest.
net_auto = true;
#* Sync the auto scaling for download and upload to whichever currently has the highest scale.
net_sync = true;
#* "True" shows bitrates in base 10 (Kbps, Mbps). "False" shows bitrates in binary sizes (Kibps, Mibps, etc.). "Auto" uses base_10_sizes.
base_10_bitrate = false;
#* Show battery stats in top right if battery is present.
show_battery = true;
#* Which battery to use if multiple are present. "Auto" for auto detection.
selected_battery = "Auto";
#* Show power stats of battery next to charge indicator.
show_battery_watts = true;
#* Measure PCIe throughput on NVIDIA cards, may impact performance on certain cards.
nvml_measure_pcie_speeds = true;
#* Horizontally mirror the GPU graph.
gpu_mirror_graph = false;
};
};
};
}

View File

@ -0,0 +1,9 @@
{
lib,
mylib,
...
}: {
enable = lib.mkEnableOption "Enable the btop system monitor";
cuda = lib.mkEnableOption "Enable Cuda support for btop";
}

View File

@ -0,0 +1,49 @@
{
config,
lib,
mylib,
pkgs,
...
}: let
inherit (config.modules) chromium;
in {
options.modules.chromium = import ./options.nix {inherit lib mylib;};
config = lib.mkIf chromium.enable {
home.packages = with pkgs;
builtins.concatLists [
(lib.optionals chromium.google [
google-chrome # Trash, but required for decker pdf export
# Required for some flatpak compatibility
(pkgs.writeShellScriptBin "chrome" "exec -a $0 ${google-chrome}/bin/google-chrome-stable $@")
])
];
programs.chromium = {
enable = true;
commandLineArgs = [
"--ignore-gpu-blocklist"
"--use-angle=" # Prevents chromium from spamming stdout and crashing
"--ozone-platform=wayland"
];
# TODO: Extensions for ungoogled, see https://discourse.nixos.org/t/home-manager-ungoogled-chromium-with-extensions/15214
# package = pkgs.ungoogled-chromium;
extensions = [
{id = "oboonakemofpalcgghocfoadofidjkkk";} # KeepassXC Browser
{id = "pkehgijcmpdhfbdbbnkijodmdjhbjlgp";} # Privacy Badger
{id = "jplgfhpmjnbigmhklmmbgecoobifkmpa";} # ProtonVPN
{id = "ddkjiahejlhfcafbddmgiahcphecmpfh";} # UBlock Origin Lite
# No longer supported after Manifest v3 (joke browser)
# {id = "cjpalhdlnbpafiamejdnhcphjbkeiagm";} # UBlock Origin
# {id = "lckanjgmijmafbedllaakclkaicjfmnk";} # ClearURLs
# {id = "njdfdhgcmkocbgbhcioffdbicglldapd";} # LocalCDN
# {id = "jaoafjdoijdconemdmodhbfpianehlon";} # Skip Redirect
];
};
};
}

View File

@ -0,0 +1,10 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "Chromium";
google = mkEnableOption "Google Chrome";
}

View File

@ -0,0 +1,102 @@
import fileinput
import re
from typing import Callable
# This dict gets defined before.
# The code is templated by nix to fill the color values automatically.
# colors: dict[str, str] = {
# "rosewater": "f5e0dc",
# "flamingo": "f2cdcd",
# }
colors: dict[str, str]
# We don't want the accent aliases here
del colors["accent"]
del colors["accentHl"]
del colors["accentDim"]
del colors["accentText"]
def getRule(
line: str,
value: str,
) -> Callable[[str, str, str], str] | None:
"""Obtain a substitution rule for a line"""
# This contains each rule assigned to a pattern
rules: dict[str, Callable[[str, str, str], str]] = {
# "#ffffff" -> ${color.hexS.white}
f'"#{value}"': lambda line, name, value: line.replace(
f'"#{value}"', f"${{color.hexS.{name}}}"
),
# '#ffffff' -> ${color.hexS.white}
f"'#{value}'": lambda line, name, value: line.replace(
f"'#{value}'", f"${{color.hexS.{name}}}"
),
# #ffffff -> ${color.hexS.white}
f"#{value}": lambda line, name, value: line.replace(
f"#{value}", f"${{color.hexS.{name}}}"
),
# "ffffff" -> ${color.hex.white}
f'"{value}"': lambda line, name, value: line.replace(
f'"{value}"', f"${{color.hex.{name}}}"
),
# 'ffffff' -> ${color.hex.white}
f"'{value}'": lambda line, name, value: line.replace(
f"'{value}'", f"${{color.hex.{name}}}"
),
# ffffff -> ${color.hex.white}
f"{value}": lambda line, name, value: line.replace(
f"{value}", f"${{color.hex.{name}}}"
),
# #${color.hex.white} -> ${color.hexS.white}
"#${color.hex.": lambda line, name, value: line.replace(
"#${color.hex.", "${color.hexS."
),
# ff,ff,ff -> ${color.rgbS.white}
f"{value[0:2]},{value[2:4]},{value[4:6]}": lambda line, name, value: line.replace(
f"{value[0:2]},{value[2:4]},{value[4:6]}", f"${{color.rgbS.{name}}}"
),
}
for pattern, rule in rules.items():
# If the line matches the pattern, use this rule
if len(re.findall(pattern, line, re.IGNORECASE)) > 0:
return rule
return None
def applyColorToLine(
line: str,
name: str,
value: str,
) -> str:
"""Apply a single color to a single line"""
result: str = line
rule: Callable[[str, str, str], str] | None = getRule(result, value)
while rule is not None:
result = rule(line, name, value)
# We apply rules until no rule can be applied anymore
rule = getRule(result, value)
return result
def applyColorsToLine(
line: str,
) -> None:
"""Apply all defined colors to a single line"""
result: str = line
for name, value in colors.items():
result = applyColorToLine(result, name, value)
# Print to stdout
print(result)
# Apply transformation to every line from stdin
for line in fileinput.input():
applyColorsToLine(line.rstrip())

View File

@ -0,0 +1,117 @@
{
config,
lib,
mylib,
pkgs,
...
}: let
inherit (config.modules) color;
in {
options.modules.color = import ./options.nix {inherit lib mylib pkgs;};
config = {
home.packages = let
mkPythonColorDef = name: value: " '${name}': '${value}',";
# Helper script that processes a visual mode selection and replaces
# referenced colors in-place with their counterparts in this module.
# Usage: ":'<,'>!applyColors<cr>"
applyColors =
pkgs.writers.writePython3Bin
"applyColors"
{
doCheck = false;
}
(builtins.concatStringsSep "\n" [
"colors: dict[str, str] = {"
(color.hex
|> builtins.mapAttrs mkPythonColorDef
|> builtins.attrValues
|> builtins.concatStringsSep "\n")
"}"
(builtins.readFile ./applyColors.py)
]);
mkBashColorEcho = let
pastel = "${pkgs.pastel}/bin/pastel";
in
name: value: ''printf "%-12s" " ${name}:" && ${pastel} color "${value}" | ${pastel} format hex'';
# Helper script that prints the color scheme to the terminal
printNixColors =
pkgs.writeShellScriptBin
"printNixColors"
(builtins.concatStringsSep "\n" [
''echo " ${color.scheme}:"''
''echo ${lib.concatStrings (lib.replicate 20 "=")}''
(color.hexS
|> builtins.mapAttrs mkBashColorEcho
|> builtins.attrValues
|> builtins.concatStringsSep "\n")
''echo ${lib.concatStrings (lib.replicate 20 "=")}''
]);
in
[
applyColors
printNixColors
]
++ (lib.optionals color.installPackages [color.iconPackage color.cursorPackage])
++ (lib.optionals color.installPackages color.extraPackages);
# This module sets its own options to the values specified in a colorscheme file.
modules.color = let
scheme = import ./schemes/${color.scheme}.nix;
# Add the aliases
colorDefs =
scheme
// {
accent = scheme.${color.accent};
accentHl = scheme.${color.accentHl};
accentDim = scheme.${color.accentDim};
accentText = scheme.${color.accentText};
};
mkColorAssignment = key: {
${key} = colorDefs.${key};
};
mkStringColorAssignment = key: {
${key} = "#${colorDefs.${key}}";
};
mkRgbColorAssignment = key: {
${key} = mylib.color.hexToRGB colorDefs.${key};
};
mkRgbStringColorAssignment = key: {
${key} = mylib.color.hexToRGBString "," colorDefs.${key};
};
in {
# RRGGBB (0-F)
hex =
colorDefs
|> builtins.attrNames
|> builtins.map mkColorAssignment
|> lib.mergeAttrsList;
# #RRGGBB (0-F)
hexS =
colorDefs
|> builtins.attrNames
|> builtins.map mkStringColorAssignment
|> lib.mergeAttrsList;
# [RR GG BB] (0-255)
rgb =
colorDefs
|> builtins.attrNames
|> builtins.map mkRgbColorAssignment
|> lib.mergeAttrsList;
# RR,GG,BB (0-255)
rgbS =
colorDefs
|> builtins.attrNames
|> builtins.map mkRgbStringColorAssignment
|> lib.mergeAttrsList;
};
};
}

View File

@ -0,0 +1,191 @@
{
lib,
mylib,
pkgs,
...
}: let
colorKeys = [
"rosewater"
"flamingo"
"pink"
"mauve"
"red"
"maroon"
"peach"
"yellow"
"green"
"teal"
"sky"
"sapphire"
"blue"
"lavender"
"text"
"subtext1"
"subtext0"
"overlay2"
"overlay1"
"overlay0"
"surface2"
"surface1"
"surface0"
"base"
"mantle"
"crust"
];
in rec {
scheme = lib.mkOption {
type = lib.types.enum [
"catppuccin-latte"
"catppuccin-mocha"
];
description = "The color scheme to use";
example = "catppuccin-mocha";
default = "catppuccin-mocha";
};
font = lib.mkOption {
type = lib.types.str;
description = "The font to use";
example = "JetBrainsMono Nerd Font Mono";
default = "JetBrainsMono Nerd Font Mono";
};
cursor = lib.mkOption {
type = lib.types.str;
description = "The cursor to use";
example = "Bibata-Modern-Classic";
default = "Bibata-Modern-Classic";
};
cursorSize = lib.mkOption {
type = lib.types.int;
description = "The cursor size";
example = 24;
default = 24;
};
cursorPackage = lib.mkOption {
type = lib.types.package;
description = "The cursor package";
example = pkgs.bibata-cursors;
default = pkgs.bibata-cursors;
};
iconTheme = lib.mkOption {
type = lib.types.str;
description = "The icon theme to use";
example = "Papirus";
default = "Papirus";
};
iconPackage = lib.mkOption {
type = lib.types.package;
description = "The icon theme package";
example = pkgs.papirus-icon-theme;
default = pkgs.papirus-icon-theme;
};
extraPackages = lib.mkOption {
type = lib.types.listOf lib.types.package;
description = "Extra packages to install";
example = ''
[
pkgs.bibata-cursors
]
'';
default = [];
};
installPackages = lib.mkEnableOption "Install cursor and icon themes";
# This option is set automatically
wallpapers = let
# Collect all the available wallpapers.
# We can't do this in default.nix as the value
# needs to be available during option evaluation.
wallpapers = let
rmFileExt = file: builtins.replaceStrings [".jpg"] [""] file;
rmBasePath = file: let
matches = builtins.match "/.*/(.*)" file;
in
if matches == null
then file
else (builtins.head matches);
in
lib.filesystem.listFilesRecursive ../../../wallpapers
|> builtins.map builtins.toString
|> builtins.map rmFileExt
|> builtins.map rmBasePath;
in
lib.mkOption {
type = lib.types.listOf lib.types.str;
readOnly = true;
description = "The available wallpapers";
default = wallpapers;
};
wallpaper = lib.mkOption {
type = lib.types.enum wallpapers.default;
description = "The wallpaper to use";
example = "Foggy-Lake";
default = "Foggy-Lake";
};
# Some semantic aliases for colors
accent = lib.mkOption {
type = lib.types.enum colorKeys;
description = "The accent color to use";
example = "mauve";
default = "mauve";
};
accentHl = lib.mkOption {
type = lib.types.enum colorKeys;
description = "The accented accent color to use";
example = "pink";
default = "pink";
};
accentDim = lib.mkOption {
type = lib.types.enum colorKeys;
description = "The dim accent color to use";
example = "lavender";
default = "lavender";
};
accentText = lib.mkOption {
type = lib.types.enum colorKeys;
description = "The text color to use for accents";
example = "base";
default = "base";
};
# These options will be populated automatically.
hex = lib.mkOption {
type = lib.types.attrs;
readOnly = true;
description = "Colors in \"RRGGBB\" hexadecimal format";
};
hexS = lib.mkOption {
type = lib.types.attrs;
readOnly = true;
description = "Colors in \"#RRGGBB\" hexadecimal format";
};
rgb = lib.mkOption {
type = lib.types.attrs;
readOnly = true;
description = "Colors in [RR GG BB] decimal format";
};
rgbS = lib.mkOption {
type = lib.types.attrs;
readOnly = true;
description = "Colors in \"RR,GG,BB\" decimal format";
};
}

View File

@ -0,0 +1,29 @@
{
rosewater = "";
flamingo = "";
pink = "";
mauve = "";
red = "";
maroon = "";
peach = "";
yellow = "";
green = "";
teal = "";
sky = "";
sapphire = "";
blue = "";
lavender = "";
text = "";
subtext1 = "";
subtext0 = "";
overlay2 = "";
overlay1 = "";
overlay0 = "";
surface2 = "";
surface1 = "";
surface0 = "";
base = "";
mantle = "";
crust = "";
}

View File

@ -0,0 +1,29 @@
{
rosewater = "dc8a78";
flamingo = "dd7878";
pink = "ea76cb";
mauve = "8839ef";
red = "d20f39";
maroon = "e64553";
peach = "fe640b";
yellow = "df8e1d";
green = "40a02b";
teal = "179299";
sky = "04a5e5";
sapphire = "209fb5";
blue = "1e66f5";
lavender = "7287fd";
text = "4c4f69";
subtext1 = "5c5f77";
subtext0 = "6c6f85";
overlay2 = "7c7f93";
overlay1 = "8c8fa1";
overlay0 = "9ca0b0";
surface2 = "acb0be";
surface1 = "bcc0cc";
surface0 = "ccd0da";
base = "eff1f5";
mantle = "e6e9ef";
crust = "dce0e8";
}

View File

@ -0,0 +1,29 @@
{
rosewater = "f5e0dc";
flamingo = "f2cdcd";
pink = "f5c2e7";
mauve = "cba6f7";
red = "f38ba8";
maroon = "eba0ac";
peach = "fab387";
yellow = "f9e2af";
green = "a6e3a1";
teal = "94e2d5";
sky = "89dceb";
sapphire = "74c7ec";
blue = "89b4fa";
lavender = "b4befe";
text = "cdd6f4";
subtext1 = "bac2de";
subtext0 = "a6adc8";
overlay2 = "9399b2";
overlay1 = "7f849c";
overlay0 = "6c7086";
surface2 = "585b70";
surface1 = "45475a";
surface0 = "313244";
base = "1e1e2e";
mantle = "181825";
crust = "11111b";
}

View File

@ -0,0 +1,44 @@
{inputs, ...}: {
imports = [
# Obsolete modules are kept in "1_deprecated" for reference.
# My own HM modules
./beets
./btop
./chromium
./color
./docs
./fcitx
./firefox
./fish
./git
./hyprland
./hyprpanel
./kitty
./lazygit
./mpd
./neovim
./niri
./nnn
./paths
./qutebrowser
./rmpc
./rofi
./waybar
./yazi
./zathura
# HM modules imported from the flake inputs
inputs.nix-flatpak.homeManagerModules.nix-flatpak
inputs.nixvim.homeModules.nixvim
inputs.textfox.homeManagerModules.default
# inputs.niri.homeModules.niri # Imported by system module
inputs.noctalia.homeModules.default
inputs.caelestia.homeManagerModules.default
inputs.dank-material-shell.homeModules.dank-material-shell
inputs.dank-material-shell.homeModules.niri
# NOTE: Do NOT use this, use the system module (the HM module has to rely on fuse)
# inputs.impermanence.homeManagerModules.impermanence
];
}

View File

@ -0,0 +1,38 @@
{
config,
lib,
mylib,
pkgs,
...
}: let
inherit (config.modules) docs;
in {
options.modules.docs = import ./options.nix {inherit lib mylib;};
config = lib.mkIf docs.enable {
home = {
packages = with pkgs; [
inkscape
texliveFull # TODO: LaTeX packages
typst # TODO: Typst packages
];
file = {
# Collection of macros and environments I once used, but not anymore...
# "texmf/tex/latex/custom/christex.sty".source = ../../../config/latex/christex.sty;
"Notes/Obsidian/Chriphost/christex.sty".source = ../../../config/latex/christex.sty; # For old obsidian notes
".indentconfig.yaml".source = ../../../config/latex/.indentconfig.yaml;
".indentsettings.yaml".source = ../../../config/latex/.indentsettings.yaml;
# TODO: These don't belong into a latex module
"Notes/Obsidian/Chriphost/.vimrc".source = ../../../config/obsidian/.vimrc;
"Notes/Obsidian/Chriphost/latex_snippets.json".source = ../../../config/obsidian/latex_snippets.json; # TODO: Symlink
"Notes/Obsidian/Chriphost/.obsidian/snippets/latex_preview.css".source = ../../../config/obsidian/css_snippets/latex_preview.css;
"Notes/Obsidian/Chriphost/.obsidian/snippets/center_image.css".source = ../../../config/obsidian/css_snippets/center_image.css;
};
};
};
}

View File

@ -0,0 +1,9 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "Enable Document Support (e.g. LaTeX)";
}

View File

@ -0,0 +1,614 @@
{
config,
lib,
mylib,
pkgs,
...
}: let
inherit (config.modules) fcitx;
in {
options.modules.fcitx = import ./options.nix {inherit lib mylib;};
config = lib.mkIf fcitx.enable {
i18n.inputMethod = {
enable = true;
type = "fcitx5";
fcitx5 = {
waylandFrontend = true;
addons = with pkgs; [
fcitx5-gtk
# fcitx5-configtool
catppuccin-fcitx5
kdePackages.fcitx5-qt # QT5
kdePackages.fcitx5-chinese-addons
qt6Packages.fcitx5-qt # QT6
qt6Packages.fcitx5-chinese-addons
];
settings = {
inputMethod = {
GroupOrder = {
"0" = "Default";
};
"Groups/0" = {
# Group Name
Name = "Default";
# Layout
"Default Layout" = "us";
# Default Input Method
DefaultIM = "pinyin";
};
"Groups/0/Items/0" = {
# Name
Name = "keyboard-us";
# Layout
# Layout=
};
"Groups/0/Items/1" = {
# Name
Name = "pinyin";
# Layout
# Layout=
};
};
globalOptions = {
Hotkey = {
# Enumerate when press trigger key repeatedly
EnumerateWithTriggerKeys = true;
# Temporally switch between first and current Input Method
# AltTriggerKeys=
# Enumerate Input Method Forward
# EnumerateForwardKeys=
# Enumerate Input Method Backward
# EnumerateBackwardKeys=
# Skip first input method while enumerating
EnumerateSkipFirst = false;
# Enumerate Input Method Group Forward
# EnumerateGroupForwardKeys=
# Enumerate Input Method Group Backward
# EnumerateGroupBackwardKeys=
# Activate Input Method
# ActivateKeys=
# Deactivate Input Method
# DeactivateKeys=
};
"Hotkey/TriggerKeys" = {
"0" = "Super+space";
};
"Hotkey/PrevPage" = {
"0" = "Up";
};
"Hotkey/NextPage" = {
"0" = "Down";
};
"Hotkey/PrevCandidate" = {
"0" = "Shift+Tab";
};
"Hotkey/NextCandidate" = {
"0" = "Tab";
};
"Hotkey/TogglePreedit" = {
"0" = "Control+Alt+P";
};
"Behavior" = {
# Active By Default
ActiveByDefault = false;
# Reset state on Focus In
resetStateWhenFocusIn = "No";
# Share Input State
ShareInputState = "All";
# Show preedit in application
PreeditEnabledByDefault = true;
# Show Input Method Information when switch input method
ShowInputMethodInformation = true;
# Show Input Method Information when changing focus
showInputMethodInformationWhenFocusIn = false;
# Show compact input method information
CompactInputMethodInformation = false;
# Show first input method information
ShowFirstInputMethodInformation = true;
# Default page size
DefaultPageSize = 5;
# Override Xkb Option
OverrideXkbOption = false;
# Custom Xkb Option
# CustomXkbOption=
# Force Enabled Addons
# EnabledAddons=
# Force Disabled Addons
# DisabledAddons=
# Preload input method to be used by default
PreloadInputMethod = true;
# Allow input method in the password field
AllowInputMethodForPassword = false;
# Show preedit text when typing password
ShowPreeditForPassword = false;
# Interval of saving user data in minutes
AutoSavePeriod = 30;
};
};
addons = {
chttrans.globalSection = {
# Translate engine
Engine = "OpenCC";
# Toggle key
# Hotkey=
# Enabled Input Methods
# EnabledIM=
# OpenCC profile for Simplified to Traditional
# OpenCCS2TProfile=
# OpenCC profile for Traditional to Simplified
# OpenCCT2SProfile=
};
classicui.globalSection = {
# Vertical Candidate List
"Vertical Candidate List" = false;
# Use mouse wheel to go to prev or next page
WheelForPaging = true;
# Font
Font = "Sans 12";
# Menu Font
MenuFont = "Sans 12";
# Tray Font
TrayFont = "Sans Bold 10";
# Tray Label Outline Color
TrayOutlineColor = "#000000";
# Tray Label Text Color
TrayTextColor = "#ffffff";
# Prefer Text Icon
PreferTextIcon = false;
# Show Layout Name In Icon
ShowLayoutNameInIcon = true;
# Use input method language to display text
UseInputMethodLanguageToDisplayText = true;
# Theme
Theme = "catppuccin-mocha-lavender";
# Dark Theme
DarkTheme = "catppuccin-mocha-lavender";
# Follow system light/dark color scheme
# NOTE: Doesn't work since I don't set up the environment
# so apps can detect if light/dark mode is used
UseDarkTheme = true;
# Follow system accent color if it is supported by theme and desktop
UseAccentColor = true;
# Use Per Screen DPI on X11
PerScreenDPI = true;
# Force font DPI on Wayland
ForceWaylandDPI = 0;
# Enable fractional scale under Wayland
EnableFractionalScale = true;
};
clipboard.globalSection = {
# Trigger Key
# TriggerKey=
# Paste Primary
# PastePrimaryKey=
# Number of entries
"Number of entries" = 5;
};
cloudpinyin.globalSection = {
# Minimum Pinyin Length
MinimumPinyinLength = 4;
# Backend
Backend = "GoogleCN";
# Proxy
# Proxy=
};
cloudpinyin.sections = {
"Toggle Key" = {
"0" = "Control+Alt+Shift+C";
};
};
fullwidth.globalSection = {
# Toggle key
# Hotkey=
};
imselector.globalSection = {
# Trigger Key
# TriggerKey=
# Trigger Key for only current input context
# TriggerKeyLocal=
# Hotkey for switching to the N-th input method
# SwitchKey=
# Hotkey for switching to the N-th input method for only current input context
# SwitchKeyLocal=
};
keyboard.globalSection = {
# Page size
PageSize = 5;
# Enable emoji in hint
EnableEmoji = false;
# Enable emoji in quickphrase
EnableQuickPhraseEmoji = false;
# Choose key modifier
"Choose Modifier" = "Alt";
# Enable hint by default
EnableHintByDefault = false;
# Trigger hint mode for one time
# "One Time Hint Trigger"=
# Use new compose behavior
UseNewComposeBehavior = true;
# Type special characters with long press
EnableLongPress = false;
};
keyboard.sections = {
"PrevCandidate" = {
"0" = "Shift+Tab";
};
"NextCandidate" = {
"0" = "Tab";
};
"Hint Trigger" = {
"0" = "Control+Alt+H";
};
"LongPressBlocklist" = {
"0" = "konsole";
};
};
notifications.globalSection = {
# Hidden Notifications
# HiddenNotifications=
};
pinyin.globalSection = {
# Shuangpin Profile
ShuangpinProfile = "Ziranma";
# Show current shuangpin mode
ShowShuangpinMode = true;
# Page size
PageSize = 7;
# Enable Spell
SpellEnabled = false;
# Enable Symbols
SymbolsEnabled = true;
# Enable Chaizi
ChaiziEnabled = false;
# Enable Characters in Unicode CJK Extension B
ExtBEnabled = true;
# Enable Cloud Pinyin
CloudPinyinEnabled = true;
# Cloud Pinyin Index
CloudPinyinIndex = 2;
# Show animation when Cloud Pinyin is loading
CloudPinyinAnimation = true;
# Always show Cloud Pinyin place holder
KeepCloudPinyinPlaceHolder = false;
# Preedit Mode
PreeditMode = "Composing pinyin";
# Fix embedded preedit cursor at the beginning of the preedit
PreeditCursorPositionAtBeginning = true;
# Show complete pinyin in preedit
PinyinInPreedit = false;
# Enable Prediction
Prediction = false;
# Prediction Size
PredictionSize = 10;
# Action when switching input method
SwitchInputMethodBehavior = "Commit current preedit";
# Forget word
# ForgetWord=
# Select 2nd Candidate
# SecondCandidate=
# Select 3rd Candidate
# ThirdCandidate=
# Use Keypad as Selection key
UseKeypadAsSelection = false;
# Use BackSpace to cancel the selection
BackSpaceToUnselect = true;
# Number of Sentences
"Number of sentence" = 2;
# Prompt long word length when input length over (0 for disable)
LongWordLengthLimit = 4;
# Key to trigger quickphrase
# QuickPhraseKey=
# Use V to trigger quickphrase
VAsQuickphrase = false;
# FirstRun
FirstRun = false;
};
pinyin.sections = {
"PrevPage" = {
"0" = "Up";
};
"NextPage" = {
"0" = "Down";
};
"PrevCandidate" = {
"0" = "Shift+Tab";
};
"NextCandidate" = {
"0" = "Tab";
};
"CurrentCandidate" = {
"0" = "space";
"1" = "KP_Space";
};
"CommitRawInput" = {
"0" = "Return";
"1" = "KP_Enter";
"2" = "Control+Return";
"3" = "Control+KP_Enter";
"4" = "Shift+Return";
"5" = "Shift+KP_Enter";
"6" = "Control+Shift+Return";
"7" = "Control+Shift+KP_Enter";
};
"ChooseCharFromPhrase" = {
"0" = "bracketleft";
"1" = "bracketright";
};
"FilterByStroke" = {
"0" = "grave";
};
"QuickPhraseTriggerRegex" = {
"0" = ".(/|@)$";
"1" = "^(www|bbs|forum|mail|bbs)''.";
"2" = "^(http|https|ftp|telnet|mailto):";
};
"Fuzzy" = {
# ue -> ve
VE_UE = true;
# Common Typo
NG_GN = true;
# Inner Segment (xian -> xi'an)
Inner = true;
# Inner Segment for Short Pinyin (qie -> qi'e)
InnerShort = true;
# Match partial finals (e -> en, eng, ei)
PartialFinal = true;
# Match partial shuangpin if input length is longer than 4
PartialSp = false;
# u <-> v
V_U = false;
# an <-> ang
AN_ANG = false;
# en <-> eng
EN_ENG = false;
# ian <-> iang
IAN_IANG = false;
# in <-> ing
IN_ING = false;
# u <-> ou
U_OU = false;
# uan <-> uang
UAN_UANG = false;
# c <-> ch
C_CH = false;
# f <-> h
F_H = false;
# l <-> n
L_N = false;
# s <-> sh
S_SH = false;
# z <-> zh
Z_ZH = false;
# Correction Layout
Correction = "None";
};
};
punctuation.globalSection = {
# Toggle key
# Hotkey=
# Half width punctuation after latin letter or number
HalfWidthPuncAfterLetterOrNumber = true;
# Type paired punctuations together (e.g. Quote)
TypePairedPunctuationsTogether = false;
# Enabled
Enabled = true;
};
quickphrase.globalSection = {
# Trigger Key
# TriggerKey=
# Choose key modifier
"Choose Modifier" = "None";
# Enable Spell check
Spell = true;
# Fallback Spell check language
FallbackSpellLanguage = "en";
};
spell.sections = {
"ProviderOrder" = {
"0" = "Presage";
"1" = "Custom";
"2" = "Enchant";
};
};
table.globalSection = {
# Modify dictionary
# ModifyDictionaryKey=
# Forget word
# ForgetWord=
# Lookup pinyin
# LookupPinyinKey=
# Enable Prediction
Prediction = false;
# Prediction Size
PredictionSize = 10;
};
unicode.sections = {
"TriggerKey" = {
"0" = "Control+Alt+Shift+U";
};
"DirectUnicodeMode" = {
"0" = "Control+Shift+U";
};
};
waylandim.globalSection = {
# Detect current running application (Need restart)
DetectApplication = true;
};
xcb.globalSection = {
# Allow Overriding System XKB Settings
"Allow Overriding System XKB Settings" = true;
# Always set layout to be only group layout
AlwaysSetToGroupLayout = true;
};
};
};
};
};
};
}

View File

@ -0,0 +1,7 @@
{
lib,
mylib,
...
}: {
enable = lib.mkEnableOption "Enable the fcitx5 input method";
}

View File

@ -0,0 +1,113 @@
let
mkBm = name: url: {
name = name;
url = url;
};
in [
{
toolbar = true;
bookmarks = [
# NixOS
{
name = "NixOS";
bookmarks = [
(mkBm "Package Search" "https://search.nixos.org/packages")
(mkBm "Option Search" "https://search.nixos.org/options?")
(mkBm "Function Search" "https://noogle.dev/")
(mkBm "HM Search" "https://mipmip.github.io/home-manager-option-search/")
(mkBm "NUR Search" "https://nur.nix-community.org/")
(mkBm "Nixpkgs Version Search" "https://lazamar.co.uk/nix-versions/")
(mkBm "Nixpkgs PR Tracker" "https://nixpk.gs/pr-tracker.html")
"separator"
(mkBm "NixOS Wiki" "https://wiki.nixos.org/wiki/NixOS_Wiki")
(mkBm "Nixpkgs Issues" "https://github.com/NixOS/nixpkgs/issues")
(mkBm "Nixpkgs Manual" "https://nixos.org/manual/nixpkgs/unstable/")
(mkBm "NixOS Manual" "https://nixos.org/manual/nixos/unstable/")
(mkBm "Nix Manual" "https://nix.dev/manual/nix/stable/")
];
}
(mkBm "Searchix" "https://searchix.ovh/")
(mkBm "Latest" "https://discourse.nixos.org/latest")
"separator"
# HomeLab
{
name = "Lab";
bookmarks = [
(mkBm "LAN Smart Switch" "http://192.168.86.2/")
(mkBm "WiFi Access Point" "http://192.168.86.3/")
(mkBm "OPNsense" "https://192.168.86.5/")
(mkBm "Synology DS223j" "https://synology.think.chriphost.de/")
(mkBm "PVE Direct" "https://192.168.86.4:8006/#v1:0:18:4:::::::")
(mkBm "PVF Direct" "https://192.168.86.13:8006/#v1:0:18:4:::::::")
(mkBm "Portainer" "https://portainer.think.chriphost.de/")
"separator"
(mkBm "Local NGINX" "https://nginx.local.chriphost.de/")
(mkBm "Think NGINX" "https://nginx.think.chriphost.de/")
(mkBm "VPS NGINX" "http://vps.chriphost.de:51810/")
(mkBm "WUD ServeNix" "https://update.local.chriphost.de/")
(mkBm "WUD ThinkNix" "https://update.think.chriphost.de/")
];
}
(mkBm "Cloud" "https://nextcloud.local.chriphost.de/apps/files/files")
(mkBm "Immich" "https://immich.local.chriphost.de/photos")
(mkBm "Jelly" "https://jellyfin.local.chriphost.de/web/#/home.html")
(mkBm "HASS" "https://hass.think.chriphost.de/lovelace")
(mkBm "Docs" "https://paperless.local.chriphost.de/documents?sort=created&reverse=1&page=1")
(mkBm "Gitea" "https://gitea.local.chriphost.de/christoph")
# (mkBm "Chat" "http://localhost:11435/") # Local WebUI
"separator"
# Coding
{
name = "Coding";
bookmarks = [
(mkBm "C++Ref" "https://en.cppreference.com/w/")
(mkBm "Rust" "https://doc.rust-lang.org/stable/book/ch03-00-common-programming-concepts.html")
(mkBm "RustOS" "https://os.phil-opp.com/")
(mkBm "Interpreters" "https://craftinginterpreters.com/contents.html")
];
}
{
name = "\"AI\"";
bookmarks = [
(mkBm "Mistral Chat" "https://chat.mistral.ai/chat")
(mkBm "DeepSeek Chat" "https://chat.deepseek.com/")
(mkBm "Claude Chat" "https://claude.ai/new")
(mkBm "ChatGPT" "https://chatgpt.com/")
(mkBm "DeepWiki" "https://deepwiki.com/")
"separator"
(mkBm "Mistral API" "https://console.mistral.ai/usage")
(mkBm "DeepSeek API" "https://platform.deepseek.com/usage")
(mkBm "Claude API" "https://console.anthropic.com/usage")
(mkBm "OpenRouter API" "https://openrouter.ai/activity")
];
}
(mkBm "GH" "https://github.com/churl")
(mkBm "GL" "https://gitlab.com/churl")
(mkBm "SO" "https://stackoverflow.com/users/saves/17337508/all")
(mkBm "RegEx" "https://regex101.com/")
(mkBm "Shell" "https://explainshell.com/")
(mkBm "CDecl" "https://cdecl.org/")
(mkBm "ECR" "https://gallery.ecr.aws/")
(mkBm "Chmod" "https://chmod-calculator.com/")
"separator"
# Stuff
(mkBm "Spiegel" "https://www.spiegel.de/")
(mkBm "Heise" "https://www.heise.de/")
(mkBm "HN" "https://news.ycombinator.com/news")
(mkBm "Reddit" "https://www.reddit.com/user/FightingMushroom/saved/")
(mkBm "F10" "https://f10.local.chriphost.de/race/Everyone")
(mkBm "F11" "https://f11.local.chriphost.de/racepicks")
(mkBm "F11PB" "https://f11pb.local.chriphost.de/_/#/collections?collection=pbc_1736455494&filter=&sort=-%40rowid")
(mkBm "ISBNDB" "https://isbndb.com/")
(mkBm "Music" "https://bandcamp.com/chriphost")
(mkBm "Albums" "https://www.albumoftheyear.org/user/chriphost/list/307966/2025/")
];
}
]

View File

@ -0,0 +1,146 @@
{
"placements": {
"widget-overflow-fixed-list": [],
"unified-extensions-area": [
"jid1-mnnxcxisbpnsxq_jetpack-browser-action",
"_74145f27-f039-47ce-a470-a662b129930a_-browser-action",
"_b86e4813-687a-43e6-ab65-0bde4ab75758_-browser-action",
"cookieautodelete_kennydo_com-browser-action",
"skipredirect_sblask-browser-action",
"_ublacklist-browser-action",
"umatrix_raymondhill_net-browser-action",
"_2e5ff8c8-32fe-46d0-9fc8-6b8986621f3c_-browser-action",
"_287dcf75-bec6-4eec-b4f6-71948a2eea29_-browser-action",
"_d133e097-46d9-4ecc-9903-fa6a722a6e0e_-browser-action",
"_f209234a-76f0-4735-9920-eb62507a54cd_-browser-action",
"dontfuckwithpaste_raim_ist-browser-action",
"sponsorblocker_ajay_app-browser-action",
"mogultv_mogultv_org-browser-action",
"jid1-tsgsxbhncspbwq_jetpack-browser-action",
"sourcegraph-for-firefox_sourcegraph_com-browser-action",
"_b11bea1f-a888-4332-8d8a-cec2be7d24b9_-browser-action",
"_762f9885-5a13-4abd-9c77-433dcd38b8fd_-browser-action",
"_34daeb50-c2d2-4f14-886a-7160b24d66a4_-browser-action",
"smart-referer_meh_paranoid_pk-browser-action",
"jid1-ckhysaadh4nl6q_jetpack-browser-action",
"_e737d9cb-82de-4f23-83c6-76f70a82229c_-browser-action",
"_a4c4eda4-fb84-4a84-b4a1-f7c1cbf2a1ad_-browser-action",
"github-forks-addon_musicallyut_in-browser-action",
"_36bdf805-c6f2-4f41-94d2-9b646342c1dc_-browser-action",
"_605a075b-09d9-4443-bed6-4baa743f7d79_-browser-action",
"enhancerforyoutube_maximerf_addons_mozilla_org-browser-action",
"frankerfacez_frankerfacez_com-browser-action",
"freedium-browser-extension_wywywywy_com-browser-action",
"_076d8ebb-5df6-48e0-a619-99315c395644_-browser-action",
"_9350bc42-47fb-4598-ae0f-825e3dd9ceba_-browser-action",
"_a7399979-5203-4489-9861-b168187b52e1_-browser-action",
"addon_fastforward_team-browser-action",
"firefox-extension_steamdb_info-browser-action",
"_cb31ec5d-c49a-4e5a-b240-16c767444f62_-browser-action",
"_bbb880ce-43c9-47ae-b746-c3e0096c5b76_-browser-action"
],
"nav-bar": [
"back-button",
"forward-button",
"vertical-spacer",
"downloads-button",
"urlbar-container",
"save-to-pocket-button",
"_3c078156-979c-498b-8990-85f7987dd929_-browser-action",
"fxa-toolbar-menu-button",
"treestyletab_piro_sakura_ne_jp-browser-action",
"ublock0_raymondhill_net-browser-action",
"_531906d3-e22f-4a6c-a102-8057b88a1a63_-browser-action",
"display-anchors_robwu_nl-browser-action",
"tab-session-manager_sienori-browser-action",
"_d7742d87-e61d-4b78-b8a1-b469842139fa_-browser-action",
"keepassxc-browser_keepassxc_org-browser-action",
"reset-pbm-toolbar-button",
"faststream_andrews-browser-action",
"_b9db16a4-6edc-47ec-a1f4-b86292ed211d_-browser-action",
"clipper_obsidian_md-browser-action",
"zotero_chnm_gmu_edu-browser-action",
"vpn_proton_ch-browser-action",
"jid1-qofqdk4qzufgwq_jetpack-browser-action",
"unified-extensions-button"
],
"toolbar-menubar": [
"menubar-items"
],
"TabsToolbar": [
"firefox-view-button",
"tabbrowser-tabs",
"new-tab-button",
"alltabs-button"
],
"vertical-tabs": [],
"PersonalToolbar": [
"personal-bookmarks"
]
},
"seen": [
"developer-button",
"ublock0_raymondhill_net-browser-action",
"_287dcf75-bec6-4eec-b4f6-71948a2eea29_-browser-action",
"_2e5ff8c8-32fe-46d0-9fc8-6b8986621f3c_-browser-action",
"_531906d3-e22f-4a6c-a102-8057b88a1a63_-browser-action",
"_74145f27-f039-47ce-a470-a662b129930a_-browser-action",
"_b86e4813-687a-43e6-ab65-0bde4ab75758_-browser-action",
"_d133e097-46d9-4ecc-9903-fa6a722a6e0e_-browser-action",
"_d7742d87-e61d-4b78-b8a1-b469842139fa_-browser-action",
"_f209234a-76f0-4735-9920-eb62507a54cd_-browser-action",
"_ublacklist-browser-action",
"cookieautodelete_kennydo_com-browser-action",
"dontfuckwithpaste_raim_ist-browser-action",
"jid1-mnnxcxisbpnsxq_jetpack-browser-action",
"keepassxc-browser_keepassxc_org-browser-action",
"skipredirect_sblask-browser-action",
"sponsorblocker_ajay_app-browser-action",
"tab-session-manager_sienori-browser-action",
"treestyletab_piro_sakura_ne_jp-browser-action",
"umatrix_raymondhill_net-browser-action",
"mogultv_mogultv_org-browser-action",
"jid1-tsgsxbhncspbwq_jetpack-browser-action",
"display-anchors_robwu_nl-browser-action",
"github-forks-addon_musicallyut_in-browser-action",
"_a4c4eda4-fb84-4a84-b4a1-f7c1cbf2a1ad_-browser-action",
"_e737d9cb-82de-4f23-83c6-76f70a82229c_-browser-action",
"jid1-ckhysaadh4nl6q_jetpack-browser-action",
"smart-referer_meh_paranoid_pk-browser-action",
"_34daeb50-c2d2-4f14-886a-7160b24d66a4_-browser-action",
"_762f9885-5a13-4abd-9c77-433dcd38b8fd_-browser-action",
"_b11bea1f-a888-4332-8d8a-cec2be7d24b9_-browser-action",
"sourcegraph-for-firefox_sourcegraph_com-browser-action",
"_36bdf805-c6f2-4f41-94d2-9b646342c1dc_-browser-action",
"_605a075b-09d9-4443-bed6-4baa743f7d79_-browser-action",
"enhancerforyoutube_maximerf_addons_mozilla_org-browser-action",
"frankerfacez_frankerfacez_com-browser-action",
"freedium-browser-extension_wywywywy_com-browser-action",
"_076d8ebb-5df6-48e0-a619-99315c395644_-browser-action",
"_9350bc42-47fb-4598-ae0f-825e3dd9ceba_-browser-action",
"_a7399979-5203-4489-9861-b168187b52e1_-browser-action",
"vpn_proton_ch-browser-action",
"addon_fastforward_team-browser-action",
"faststream_andrews-browser-action",
"firefox-extension_steamdb_info-browser-action",
"clipper_obsidian_md-browser-action",
"zotero_chnm_gmu_edu-browser-action",
"_b9db16a4-6edc-47ec-a1f4-b86292ed211d_-browser-action",
"_cb31ec5d-c49a-4e5a-b240-16c767444f62_-browser-action",
"screenshot-button",
"_bbb880ce-43c9-47ae-b746-c3e0096c5b76_-browser-action",
"jid1-qofqdk4qzufgwq_jetpack-browser-action",
"_3c078156-979c-498b-8990-85f7987dd929_-browser-action"
],
"dirtyAreaCache": [
"nav-bar",
"PersonalToolbar",
"toolbar-menubar",
"TabsToolbar",
"widget-overflow-fixed-list",
"unified-extensions-area",
"vertical-tabs"
],
"currentVersion": 22,
"newElementCount": 9
}

View File

@ -0,0 +1,324 @@
{
config,
lib,
mylib,
pkgs,
hostname,
...
}: let
inherit (config.modules) firefox color;
in {
options.modules.firefox = import ./options.nix {inherit lib mylib;};
config = lib.mkIf firefox.enable {
textfox = {
enable = firefox.textfox;
useLegacyExtensions = false;
profiles = ["default"];
config = {
background = {
color = color.hexS.base;
};
border = {
color = color.hexS.overlay0;
width = "2px";
transition = "1.0s ease";
radius = "3px";
};
displayWindowControls = true;
displayNavButtons = true;
displayUrlbarIcons = true;
displaySidebarTools = false;
displayTitles = false;
icons = {
toolbar.extensions.enable = true;
context.extensions.enable = true;
context.firefox.enable = true;
};
tabs = {
horizontal.enable = !firefox.disableTabBar;
vertical.enable = firefox.disableTabBar;
# vertical.margin = "1rem";
};
font = {
family = color.font;
size = "14px";
accent = color.hexS.accent;
};
};
};
home.packages = with pkgs; [vdhcoapp];
home.sessionVariables = lib.mkMerge [
{
MOZ_USE_XINPUT2 = 1;
}
(lib.optionalAttrs firefox.wayland {
MOZ_ENABLE_WAYLAND = 1;
EGL_PLATFORM = "wayland";
})
(lib.optionalAttrs firefox.vaapi {
MOZ_DISABLE_RDD_SANDBOX = 1;
})
];
# Not required with rofi -drun-show-actions
# xdg.desktopEntries.firefox-private = {
# name = "Firefox (Incognito)";
# genericName = "Private web browser";
# icon = "firefox";
# exec = "firefox --private-window %U";
# terminal = false;
# categories = ["Network" "WebBrowser"];
# };
programs.firefox = {
enable = true;
# firefox-unwrapped is the pure firefox browser, wrapFirefox adds configuration ontop
package = pkgs.wrapFirefox pkgs.firefox-unwrapped {
# About policies: https://github.com/mozilla/policy-templates#enterprisepoliciesenabled
# TODO: To separate file
extraPolicies = {
CaptivePortal = false;
DisableAppUpdate = true;
DisableFirefoxAccounts = true;
DisableFirefoxScreenshots = true;
DisableFirefoxStudies = true;
DisableSetDesktopBackground = true;
DisableTelemetry = true;
DisplayBookmarksToolbar = true;
EnableTrackingProtection = {
Value = true;
Cryptomining = true;
Fingerprinting = true;
EmailTracking = true;
};
FirefoxHome = {
Highlights = false;
Search = true;
Snippets = false;
SponsoredTopSites = false;
TopSites = false;
};
FirefoxSuggest = {
ImproveSuggest = false;
SponsoredSuggestions = false;
WebSuggestions = false;
};
HardwareAcceleration = true;
# NoDefaultBookmarks = true; # Prevents HM from applying bookmarks
OfferToSaveLogins = false;
PictureInPicture = true;
SanitizeOnShutdown = {
Cache = false;
Cookies = false;
FormData = true;
History = false;
Sessions = false;
SiteSettings = false;
};
UserMessaging = {
ExtensionRecommendations = false;
FeatureRecommendations = false;
MoreFromMozilla = false;
SkipOnboarding = true;
UrlbarInteventions = false;
};
};
};
profiles = {
default = {
id = 0; # 0 is default profile
userChrome = lib.concatStringsSep "\n" [
(lib.optionalString firefox.disableTabBar ''
#TabsToolbar { display: none; }
'')
];
# TODO: To separate file
search = {
force = true; # Always override search engines
default = "kagi";
privateDefault = "kagi";
order = [
"kagi"
"wiki"
"nixos-packages"
"nixos-functions"
"nixos-wiki"
"google"
];
engines = {
kagi = {
name = "Kagi";
urls = [{template = "https://kagi.com/search?q={searchTerms}";}];
iconMapObj."16" = "https://kagi.com/favicon.ico";
definedAliases = ["@k"];
};
wiki = {
name = "Wikipedia";
urls = [{template = "https://en.wikipedia.org/wiki/Special:Search?search={searchTerms}";}];
iconMapObj."16" = "https://en.wikipedia.org/favicon.ico";
definedAliases = ["@w"];
};
nixos-packages = {
name = "NixOS Packages";
urls = [{template = "https://searchix.ovh/?query={searchTerms}";}];
iconMapObj."16" = "https://nixos.org/favicon.ico";
definedAliases = ["@np"];
};
nixos-functions = {
name = "NixOS Functions";
urls = [{template = "https://noogle.dev/q?term={searchTerms}";}];
iconMapObj."16" = "https://nixos.org/favicon.ico";
definedAliases = ["@nf"];
};
nixos-wiki = {
name = "NixOS Wiki";
urls = [{template = "https://wiki.nixos.org/w/index.php?search={searchTerms}";}];
iconMapObj."16" = "https://nixos.org/favicon.ico";
definedAliases = ["@nw"];
};
arch-wiki = {
name = "Arch Wiki";
urls = [{template = "https://wiki.archlinux.org/?search={searchTerms}";}];
iconMapObj."16" = "https://wiki.archlinux.org/favicon.ico";
definedAliases = ["@aw"];
};
nixpkgs-issues = {
name = "Nixpkgs Issues";
urls = [{template = "https://github.com/NixOS/nixpkgs/issues?q=is%3Aissue%20{searchTerms}";}];
iconMapObj."16" = "https://github.com/favicon.ico";
definedAliases = ["@i"];
};
github = {
name = "GitHub";
urls = [{template = "https://github.com/search?q={searchTerms}&type=repositories";}];
iconMapObj."16" = "https://github.com/favicon.ico";
definedAliases = ["@gh"];
};
google.metaData.alias = "@g";
# Hide bullshit
bing.metaData.hidden = true;
ddg.metaData.hidden = true;
ecosia.metaData.hidden = true;
wikipedia.metaData.hidden = true;
};
};
# TODO: To separate file
extensions = {
force = true; # Always override extensions
packages = with pkgs.nur.repos.rycee.firefox-addons; [
absolute-enable-right-click # Force enable right click to copy text
amp2html
augmented-steam
betterttv
# bypass-paywalls-clean
# c-c-search-extension # Press cc in searchbar and profit
catppuccin-mocha-mauve
# catppuccin-web-file-icons
clearurls
# cookie-autodelete
dark-background-light-text
display-_anchors # Easier linking to specific website parts
don-t-fuck-with-paste
# enhancer-for-youtube # Discontinued, use tweaks-for-youtube
fastforwardteam # skip URL shorteners
# faststream # replace video players with a faster one
frankerfacez # twitch emotes
indie-wiki-buddy
keepassxc-browser
localcdn
lovely-forks # Display notable forks on GitHub repos
# move-unloaded-tabs-for-tst # move tst tabs without them becoming active
native-mathml # native MathML instead of MathJax/MediaWiki
no-pdf-download # open pdf in browser without downloading
open-in-freedium
# plasma-integration
privacy-badger
privacy-settings
protondb-for-steam
proton-vpn
purpleadblock # twitch adblocker
return-youtube-dislikes
# rust-search-extension
search-by-image
single-file
skip-redirect
smart-referer # Limit referer link information
snowflake # Help users from censored countries access the internet
# sourcegraph # Code intelligence for GitHub/GitLap for 20+ languages
sponsorblock
steam-database
# tab-session-manager
# to-deepl
transparent-standalone-image
# tree-style-tab
# tst-fade-old-tabs
tweaks-for-youtube
twitch-auto-points
ublacklist
ublock-origin
unpaywall
video-downloadhelper
view-image
web-clipper-obsidian
youtube-shorts-block
zotero-connector
];
};
bookmarks = {
# Always override bookmarks (so we don't forget to add them through here)
force = true;
settings = import ./bookmarks.nix;
};
settings = lib.mkMerge [
(import ./settings.nix)
{
# NOTE: This has to be updated when something is changed inside firefox...
"browser.uiCustomization.state" = builtins.readFile ./customizationState.json;
"toolkit.legacyUserProfileCustomizations.stylesheets" = firefox.disableTabBar;
"identity.fxaccounts.account.device.name" = hostname;
}
(lib.optionalAttrs firefox.vaapi {
# https://github.com/elFarto/nvidia-vaapi-driver/#firefox=
"media.ffmpeg.vaapi.enabled" = true;
"media.rdd-ffmpeg.enabled" = true; # Default value
"media.av1.enabled" = true;
"gfx.x11-egl.force-enabled" = true;
"widget.dmabuf.force-enabled" = true;
})
];
};
};
};
};
}

View File

@ -0,0 +1,13 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "Firefox";
wayland = mkBoolOption false "Enable firefox wayland support";
vaapi = mkBoolOption false "Enable firefox vaapi support";
disableTabBar = mkBoolOption false "Disable the firefox tab bar (for TST)";
textfox = mkBoolOption false "Enable the TextFox theme";
}

View File

@ -0,0 +1,115 @@
{
"accessibility.force_disabled" = 1;
"app.normandy.enabled" = false; # https://mozilla.github.io/normandy/
"app.normandy.api_url" = "";
"app.update.auto" = false;
"app.shield.optoutstudies.enabled" = false;
"beacon.enabled" = false; # https://developer.mozilla.org/en-US/docs/Web/API/navigator.sendBeacon
"breakpad.reportURL" = "";
"browser.aboutConfig.showWarning" = false; # Warning when opening about:config
"browser.contentblocking.category" = "standard";
"browser.crashReports.unsubmittedCheck.autoSubmit2" = false; # don't submit backlogged reports
"browser.disableResetPrompt" = true; # "Looks like you haven't started Firefox in a while."
"browser.discovery.enabled" = false;
"browser.download.useDownloadDir" = false; # Always ask
"browser.fixup.alternate.enabled" = false; # http://www-archive.mozilla.org/docs/end-user/domain-guessing.html
"browser.formfill.enable" = false;
"browser.newtabpage.enabled" = false;
"browser.newtab.url" = "about:blank";
"browser.newtab.preload" = false;
"browser.newtabpage.activity-stream.asrouter.userprefs.cfr" = false;
"browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons" = false;
"browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features" = false;
"browser.newtabpage.activity-stream.enabled" = false; # https://wiki.mozilla.org/Firefox/Activity_Stream
"browser.newtabpage.activity-stream.telemetry" = false;
"browser.newtabpage.directory.ping" = "";
"browser.newtabpage.directory.source" = "data:text/plain,{}";
"browser.newtabpage.enhanced" = false;
"browser.newtabpage.introShown" = true;
"browser.onboarding.enabled" = false; # "New to Firefox? Let's get started!" tour
"browser.ping-centre.telemetry" = false;
"browser.send_pings" = false; # http://kb.mozillazine.org/Browser.send_pings
"browser.sessionstore.interval" = "1800000"; # Reduce File IO / SSD abuse by increasing write interval
"browser.shell.checkDefaultBrowser" = false;
"browser.startup.couldRestoreSession.count" = 2; # Restore last session
"browser.tabs.crashReporting.sendReport" = false;
"browser.toolbars.bookmarks.visibility" = "always";
"browser.urlbar.dnsResolveSingleWordsAfterSearch" = 0; # https://bugzilla.mozilla.org/1642623
"browser.urlbar.shortcuts.bookmarks" = false; # This is only the button to search in bookmarks, bookmark search works anyway if enabled
"browser.urlbar.shortcuts.history" = false;
"browser.urlbar.shortcuts.tabs" = false;
"browser.urlbar.showSearchSuggestionsFirst" = false;
"browser.urlbar.speculativeConnect.enabled" = false;
"browser.urlbar.suggest.calculator" = true;
"browser.urlbar.suggest.engines" = false;
"browser.urlbar.suggest.openpage" = false;
"browser.urlbar.suggest.searches" = true;
"browser.urlbar.suggest.quicksuggest.nonsponsored" = false;
"browser.urlbar.suggest.quicksuggest.sponsored" = false;
"browser.urlbar.unitConversion.enabled" = true;
"browser.urlbar.trimURLs" = false;
"datareporting.healthreport.uploadEnabled" = false;
"datareporting.healthreport.service.enabled" = false;
"datareporting.policy.dataSubmissionEnabled" = false;
"dom.battery.enabled" = false;
"dom.forms.autocomplete.formautofill" = false;
"dom.gamepad.enabled" = false; # Disable gamepad API to prevent USB device enumeration
"dom.security.https_only_mode" = true;
"experiments.enabled" = false;
"experiments.manifest.uri" = "";
"experiments.supported" = false;
"extensions.formautofill.addresses.enabled" = false;
"extensions.formautofill.available" = "off";
"extensions.formautofill.creditCards.available" = false;
"extensions.formautofill.creditCards.enabled" = false;
"extensions.formautofill.heuristics.enabled" = false;
"extensions.getAddons.showPane" = false; # uses Google Analytics
"extensions.htmlaboutaddons.discover.enabled" = false;
"extensions.htmlaboutaddons.recommendations.enabled" = false;
"extensions.pocket.enabled" = false;
"extensions.shield-recipe-client.enabled" = false;
"general.autoScroll" = false;
"general.smoothScroll" = true;
"geo.provider.network.url" = "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%";
"geo.provider.use_gpsd" = false;
"media.hardwaremediakeys.enabled" = false; # Do not interfere with spotify
"media.videocontrols.picture-in-picture.video-toggle.enabled" = true;
"narrate.enabled" = false;
"privacy.donottrackheader.enabled" = true;
"privacy.donottrackheader.value" = 1;
"privacy.purge_trackers.enabled" = true;
"privacy.webrtc.legacyGlobalIndicator" = false;
"privacy.webrtc.hideGlobalIndicator" = true;
"reader.parse-on-load.enabled" = false; # "reader view"
"security.family_safety.mode" = 0;
"security.pki.sha1_enforcement_level" = 1; # https://blog.mozilla.org/security/2016/10/18/phasing-out-sha-1-on-the-public-web/
"security.tls.enable_0rtt_data" = false; # https://github.com/tlswg/tls13-spec/issues/1001
"signon.autofillForms" = false;
"signon.generateion.enabled" = false;
"signon.rememberSignons" = false;
"toolkit.coverage.opt-out" = true;
"toolkit.coverage.endpoint.base" = "";
"toolkit.telemetry.unified" = false;
"toolkit.telemetry.enabled" = false;
"toolkit.telemetry.server" = "data:,";
"toolkit.telemetry.archive.enabled" = false;
"toolkit.telemetry.coverage.opt-out" = true;
"widget.use-xdg-desktop-portal" = true;
"widget.use-xdg-desktop-portal.file-picker" = 1; # 1: always, 2: auto
"widget.use-xdg-desktop-portal.location" = 2;
"widget.use-xdg-desktop-portal.mime-handler" = 2;
"widget.use-xdg-desktop-portal.native-messaging" = 0;
"widget.use-xdg-desktop-portal.open-uri" = 2;
"widget.use-xdg-desktop-portal.settings" = 2;
}

View File

@ -0,0 +1,238 @@
{
config,
lib,
mylib,
pkgs,
username,
nixosConfig,
...
}: let
inherit (config.modules) fish color;
in {
options.modules.fish = import ./options.nix {inherit lib mylib;};
config = lib.mkIf fish.enable {
# https://github.com/catppuccin/fish/blob/main/themes/Catppuccin%20Mocha.theme
home.file.".config/fish/themes/system-theme.theme".text = ''
fish_color_normal ${color.hex.text}
fish_color_command ${color.hex.blue}
fish_color_param ${color.hex.flamingo}
fish_color_keyword ${color.hex.red}
fish_color_quote ${color.hex.green}
fish_color_redirection ${color.hex.accentHl}
fish_color_end ${color.hex.peach}
fish_color_comment ${color.hex.overlay1}
fish_color_error ${color.hex.red}
fish_color_gray ${color.hex.overlay0}
fish_color_selection --background=${color.hex.surface0}
fish_color_search_match --background=${color.hex.surface0}
fish_color_option ${color.hex.green}
fish_color_operator ${color.hex.accentHl}
fish_color_escape ${color.hex.maroon}
fish_color_autosuggestion ${color.hex.overlay0}
fish_color_cancel ${color.hex.red}
fish_color_cwd ${color.hex.yellow}
fish_color_user ${color.hex.teal}
fish_color_host ${color.hex.blue}
fish_color_host_remote ${color.hex.green}
fish_color_status ${color.hex.red}
fish_pager_color_progress ${color.hex.overlay0}
fish_pager_color_prefix ${color.hex.accentHl}
fish_pager_color_completion ${color.hex.text}
fish_pager_color_description ${color.hex.overlay0}
'';
programs.fish = {
enable = true;
generateCompletions = nixosConfig.programs.fish.generateCompletions;
functions = lib.mergeAttrsList [
(lib.optionalAttrs config.modules.nnn.enable {
nnncd = {
wraps = "nnn";
description = "support nnn quit and change directory";
body = ''
# Block nesting of nnn in subshells
if test -n "$NNNLVL" -a "$NNNLVL" -ge 1
echo "nnn is already running"
return
end
# The behaviour is set to cd on quit (nnn checks if NNN_TMPFILE is set)
# If NNN_TMPFILE is set to a custom path, it must be exported for nnn to
# see. To cd on quit only on ^G, remove the "-x" from both lines below,
# without changing the paths.
if test -n "$XDG_CONFIG_HOME"
set -x NNN_TMPFILE "$XDG_CONFIG_HOME/nnn/.lastd"
else
set -x NNN_TMPFILE "$HOME/.config/nnn/.lastd"
end
# Unmask ^Q (, ^V etc.) (if required, see `stty -a`) to Quit nnn
# stty start undef
# stty stop undef
# stty lwrap undef
# stty lnext undef
# The command function allows one to alias this function to `nnn` without
# making an infinitely recursive alias
command nnn $argv
if test -e $NNN_TMPFILE
source $NNN_TMPFILE
rm $NNN_TMPFILE
end
'';
};
})
];
plugins = [];
shellInit = ''
set fish_greeting
yes | fish_config theme save "system-theme"
'';
shellAbbrs = let
# Only add " | bat" if bat is installed
batify = command: command + (lib.optionalString config.programs.bat.enable " | bat");
# Same as above but with args for bat
batifyWithArgs = command: args: command + (lib.optionalString config.programs.bat.enable (" | bat " + args));
# These can be used for my config.modules and for HM config.programs,
# as both of these add the package to home.packages
hasHomePackage = package: (mylib.modules.contains config.home.packages package);
# Only add fish abbr if package is installed
abbrify = package: abbr: (lib.optionalAttrs (hasHomePackage package) abbr);
in
lib.mkMerge [
# Abbrs that are always available are defined here.
{
# Shell basics
c = "clear";
q = "exit";
# Fish
h = batifyWithArgs "history" "-l fish"; # -l fish sets syntax highlighting to fish
abbrs = batifyWithArgs "abbr" "-l fish";
# Tools
cd = "z"; # zoxide for quickjump to previously visited locations
cdd = "zi";
b = "z -"; # jump to previous dir
mkdir = "mkdir -p"; # also create parents (-p)
blk = batify "lsblk -o NAME,LABEL,PARTLABEL,FSTYPE,SIZE,FSUSE%,MOUNTPOINT";
blkids = batify "lsblk -o NAME,LABEL,FSTYPE,SIZE,PARTLABEL,MODEL,ID,UUID";
watch = "watch -d -c -n 0.5";
nps = "nps -e";
nd = "nix develop";
nb = "nix build -L";
ns = "nix shell nixpkgs#";
}
# Abbrs only available if package is installed
(abbrify pkgs.duf {
disks = "duf --hide-mp '/var/*,/etc/*,/usr/*,/home/christoph/.*'";
alldisks = "duf";
})
(abbrify pkgs.eza {
ls = "eza --color=always --group-directories-first -F --git --icons=always --octal-permissions";
lsl = "eza --color=always --group-directories-first -F --git --icons=always --octal-permissions -l";
lsa = "eza --color=always --group-directories-first -F --git --icons=always --octal-permissions -l -a";
tre = "eza --color=always --group-directories-first -F --git --icons=always --octal-permissions -T -L 2";
})
(abbrify pkgs.fd {find = "fd";})
(abbrify pkgs.fzf {fuzzy = "fzf --preview 'bat --color=always --style=numbers --line-range=:500 {}'";})
(abbrify pkgs.gdu {
# du = "gdu";
storage = "gdu";
})
(abbrify pkgs.git {
gs = "git status";
gd = "git diff --output-indicator-new=' ' --output-indicator-old=' '";
gl = "git log --all --graph --pretty=format:'%C(magenta)%h %C(white) %an %ar%C(auto) %D%n%s%n'";
ga = "git add";
gap = "git add --patch";
gc = "git commit --verbose";
gcm = "git commit -m";
gcl = "git clone";
})
(lib.optionalAttrs config.modules.kitty.enable {ssh = "kitty +kitten ssh";})
(abbrify pkgs.lazygit {lg = "lazygit";})
(abbrify pkgs.nix-search-tv {search = "nix-search-tv print --indexes 'nixos,home-manager,nixpkgs,nur' | fzf --preview 'nix-search-tv preview {}' --scheme history";})
# Doesn't work with abbrify because I have nnn.override...
(lib.optionalAttrs config.modules.nnn.enable {n = "nnncd -a";})
(lib.optionalAttrs config.modules.nnn.enable {np = "nnncd -a -P p";})
(abbrify pkgs.ranger {r = "ranger --choosedir=$HOME/.rangerdir; set LASTDIR (cat $HOME/.rangerdir); cd $LASTDIR";})
(abbrify pkgs.ripgrep rec {
rg = "rg --trim --pretty";
# grep = rg;
})
(lib.optionalAttrs config.modules.rmpc.enable {r = "rcmp";})
(abbrify pkgs.rsync rec {
rsync = "rsync -ahv --inplace --partial --info=progress2";
copy = rsync;
})
# (abbrify pkgs.sd {sed = "sd";})
];
};
programs.starship = {
enable = true;
enableFishIntegration = config.modules.fish.enable;
settings = {
# Other config here
format = "$all"; # Remove this line to disable the default prompt format
palette = "system-theme";
# https://github.com/catppuccin/starship/blob/main/themes/mocha.toml
palettes."system-theme" = {
rosewater = color.hexS.rosewater;
flamingo = color.hexS.flamingo;
pink = color.hexS.accentHl;
mauve = color.hexS.accent;
red = color.hexS.red;
maroon = color.hexS.maroon;
peach = color.hexS.peach;
yellow = color.hexS.yellow;
green = color.hexS.green;
teal = color.hexS.teal;
sky = color.hexS.sky;
sapphire = color.hexS.sapphire;
blue = color.hexS.blue;
lavender = color.hexS.lavender;
text = color.hexS.text;
subtext1 = color.hexS.subtext1;
subtext0 = color.hexS.subtext0;
overlay2 = color.hexS.overlay2;
overlay1 = color.hexS.overlay1;
overlay0 = color.hexS.overlay0;
surface2 = color.hexS.surface2;
surface1 = color.hexS.surface1;
surface0 = color.hexS.surface0;
base = color.hexS.accentText;
mantle = color.hexS.mantle;
crust = color.hexS.crust;
};
};
};
};
}

View File

@ -0,0 +1,9 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "Fish";
}

View File

@ -0,0 +1,123 @@
{
config,
nixosConfig,
lib,
mylib,
pkgs,
...
}: let
inherit (config.modules) git;
in {
options.modules.git = import ./options.nix {inherit lib mylib;};
config = lib.mkIf git.enable {
programs.diff-so-fancy = {
enable = true;
enableGitIntegration = true;
settings = {
changeHunkIndicators = true;
markEmptyLines = false;
stripLeadingSymbols = true;
};
};
programs.git = {
enable = true;
# settings.user.email = "christoph.urlacher@protonmail.com";
# settings.user.name = "Christoph Urlacher";
settings = {
user = {
email = git.userEmail;
name = git.userName;
};
core = {
compression = 9;
# whitespace = "error";
preloadindex = true;
};
init = {
defaultBranch = "main";
};
gpg = {
ssh = {
allowedSignersFile = "~/.ssh/allowed_signers";
};
};
status = {
branch = true;
showStash = true;
showUntrackedFiles = "all";
};
pull = {
default = "current";
rebase = true;
};
push = {
autoSetupRemote = true;
default = "current";
followTags = true;
};
rebase = {
autoStash = true;
missingCommitsCheck = "warn";
};
diff = {
context = 3;
renames = "copies";
interHunkContext = 10;
};
interactive = {
diffFilter = "${pkgs.diff-so-fancy}/bin/diff-so-fancy --patch";
singlekey = true;
};
log = {
abbrevCommit = true;
graphColors = "blue,yellow,cyan,magenta,green,red";
};
branch = {
sort = "-committerdate";
};
tag = {
sort = "-taggerdate";
};
pager = {
branch = false;
tag = false;
};
url = {
"ssh://git@gitea.local.chriphost.de:222/christoph/" = {
insteadOf = "gitea:";
};
"git@github.com:" = {
insteadOf = "github:";
};
};
};
signing = {
signByDefault = git.signCommits;
format = "ssh";
key = "~/.ssh/id_ed25519.pub";
};
lfs.enable = true;
};
};
}

View File

@ -0,0 +1,25 @@
{
lib,
mylib,
...
}: {
enable = lib.mkEnableOption "Enable git";
userName = lib.mkOption {
type = lib.types.str;
description = "The user's name";
example = ''
"John Doe"
'';
};
userEmail = lib.mkOption {
type = lib.types.str;
description = "The user's email address";
example = ''
"john@doe.com"
'';
};
signCommits = lib.mkEnableOption "Enable commit signing";
}

View File

@ -0,0 +1,31 @@
{
lib,
pkgs,
config,
hyprland,
}:
builtins.concatLists [
(lib.optionals hyprland.dunst.enable ["dunst"]) # Notifications
(lib.optionals hyprland.hyprpanel.enable ["hyprpanel"]) # Panel
(lib.optionals hyprland.caelestia.enable ["caelestia shell"]) # Panel/Shell # TODO: Crashes on startup
[
# Start clipboard management
"wl-paste -t text --watch clipman store --no-persist"
"wl-paste -p -t text --watch clipman store -P --histpath=\"~/.local/share/clipman-primary.json\""
"hyprctl setcursor ${config.home.pointerCursor.name} ${builtins.toString config.home.pointerCursor.size}"
"hyprsunset --identity"
# HACK: Hyprland doesn't set the xwayland/x11 keymap correctly
"setxkbmap -layout ${hyprland.keyboard.layout} -variant ${hyprland.keyboard.variant} -option ${hyprland.keyboard.option} -model pc104"
# HACK: Flatpak doesn't find applications in the system PATH
"systemctl --user import-environment PATH && systemctl --user restart xdg-desktop-portal.service"
# Provide a polkit authentication UI.
# This is used for example when running systemd commands without root.
# "systemctl --user start hyprpolkitagent.service"
# "${pkgs.kdePackages.polkit-kde-agent-1}/libexec/polkit-kde-authentication-agent-1"
"${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1"
]
]

View File

@ -0,0 +1,516 @@
{
config,
hyprland,
color,
}: {
enable = hyprland.caelestia.enable;
systemd = {
enable = false; # Start from hyprland autostart
target = "graphical-session.target";
environment = [];
};
settings = {
appearance = {
anim = {durations = {scale = 1;};};
font = {
family = {
clock = "Rubik";
material = "Material Symbols Rounded";
mono = color.font;
sans = color.font;
};
size = {scale = 1;};
};
padding = {scale = 1;};
rounding = {scale = 1;};
spacing = {scale = 1;};
transparency = {
base = 0.85;
enabled = false;
layers = 0.4;
};
};
background = {
desktopClock = {enabled = false;};
enabled = true;
# Lags when visible on both monitors (different refresh rates?)
visualiser = {
autoHide = true;
blur = true;
enabled = false;
rounding = 1;
spacing = 1;
};
};
bar = {
clock = {showIcon = true;};
dragThreshold = 20;
entries = [
{
enabled = true;
id = "logo";
}
{
enabled = true;
id = "workspaces";
}
{
enabled = true;
id = "spacer";
}
{
enabled = true;
id = "activeWindow";
}
{
enabled = true;
id = "spacer";
}
{
enabled = true;
id = "clock";
}
{
enabled = true;
id = "tray";
}
{
enabled = true;
id = "statusIcons";
}
{
enabled = true;
id = "power";
}
];
persistent = true;
popouts = {
activeWindow = true;
statusIcons = true;
tray = true;
};
scrollActions = {
brightness = false;
volume = true;
workspaces = true;
};
showOnHover = true;
status = {
showAudio = true;
showBattery = false;
showBluetooth = true;
showKbLayout = false;
showLockStatus = true;
showMicrophone = false;
showNetwork = true;
};
tray = {
background = true;
compact = false;
iconSubs = [];
recolour = false;
};
workspaces = {
activeIndicator = true;
activeLabel = "󰮯";
activeTrail = true;
label = " ";
occupiedBg = false;
occupiedLabel = "󰮯";
perMonitorWorkspaces = false;
showWindows = false;
shown = 10;
# Pick them here: https://fonts.google.com/icons
specialWorkspaceIcons = [
{
icon = "music_note";
name = "rmpc";
}
{
icon = "memory";
name = "btop";
}
{
icon = "mark_chat_unread";
name = "ferdium";
}
{
icon = "network_intelligence";
name = "msty";
}
];
};
};
border = {
rounding = 25;
thickness = 10;
};
dashboard = {
dragThreshold = 50;
enabled = true;
mediaUpdateInterval = 500;
showOnHover = true;
};
general = {
apps = {
audio = ["kitty" "--title=NcpaMixer" "-e" "ncpamixer"];
explorer = ["kitty" "--title=Yazi" "-e" "yazi"];
playback = ["mpv"];
terminal = ["kitty"];
};
battery = {
criticalLevel = 3;
warnLevels = [
{
icon = "battery_android_frame_2";
level = 20;
message = "You might want to plug in a charger";
title = "Low battery";
}
{
icon = "battery_android_frame_1";
level = 10;
message = "You should probably plug in a charger <b>now</b>";
title = "Did you see the previous message?";
}
{
critical = true;
icon = "battery_android_alert";
level = 5;
message = "PLUG THE CHARGER RIGHT NOW!!";
title = "Critical battery level";
}
];
};
idle = {
inhibitWhenAudio = true;
lockBeforeSleep = true;
timeouts = [
{
idleAction = "lock";
timeout = 600;
}
{
# idleAction = "dpms off";
# returnAction = "dpms on";
idleAction = "echo 'idle'";
returnAction = "echo 'return'";
timeout = 10000;
}
{
# idleAction = ["systemctl" "suspend-then-hibernate"];
idleAction = ["echo" "'idle'"];
timeout = 20000;
}
];
};
};
launcher = {
actionPrefix = ">";
actions = [
{
command = ["autocomplete" "calc"];
dangerous = false;
description = "Do simple math equations (powered by Qalc)";
enabled = true;
icon = "calculate";
name = "Calculator";
}
{
command = ["autocomplete" "scheme"];
dangerous = false;
description = "Change the current colour scheme";
enabled = true;
icon = "palette";
name = "Scheme";
}
{
command = ["autocomplete" "wallpaper"];
dangerous = false;
description = "Change the current wallpaper";
enabled = true;
icon = "image";
name = "Wallpaper";
}
{
command = ["autocomplete" "variant"];
dangerous = false;
description = "Change the current scheme variant";
enabled = true;
icon = "colors";
name = "Variant";
}
{
command = ["autocomplete" "transparency"];
dangerous = false;
description = "Change shell transparency";
enabled = false;
icon = "opacity";
name = "Transparency";
}
{
command = ["caelestia" "wallpaper" "-r"];
dangerous = false;
description = "Switch to a random wallpaper";
enabled = false;
icon = "casino";
name = "Random";
}
{
command = ["setMode" "light"];
dangerous = false;
description = "Change the scheme to light mode";
enabled = true;
icon = "light_mode";
name = "Light";
}
{
command = ["setMode" "dark"];
dangerous = false;
description = "Change the scheme to dark mode";
enabled = true;
icon = "dark_mode";
name = "Dark";
}
{
command = ["systemctl" "poweroff"];
dangerous = true;
description = "Shutdown the system";
enabled = true;
icon = "power_settings_new";
name = "Shutdown";
}
{
command = ["systemctl" "reboot"];
dangerous = true;
description = "Reboot the system";
enabled = true;
icon = "cached";
name = "Reboot";
}
{
command = ["loginctl" "terminate-user" ""];
dangerous = true;
description = "Log out of the current session";
enabled = true;
icon = "exit_to_app";
name = "Logout";
}
{
command = ["loginctl" "lock-session"];
dangerous = false;
description = "Lock the current session";
enabled = true;
icon = "lock";
name = "Lock";
}
{
command = ["systemctl" "suspend-then-hibernate"];
dangerous = false;
description = "Suspend then hibernate";
enabled = false;
icon = "bedtime";
name = "Sleep";
}
];
dragThreshold = 50;
enableDangerousActions = true;
hiddenApps = [];
maxShown = 7;
maxWallpapers = 9;
showOnHover = false;
specialPrefix = "@";
useFuzzy = {
actions = false;
apps = false;
schemes = false;
variants = false;
wallpapers = false;
};
vimKeybinds = false;
};
lock = {recolourLogo = false;};
notifs = {
actionOnClick = false;
clearThreshold = 0.3;
defaultExpireTimeout = 5000;
expandThreshold = 20;
expire = true;
};
osd = {
enableBrightness = false;
enableMicrophone = true;
enabled = true;
hideDelay = 2000;
};
paths = {
mediaGif = "root:/assets/bongocat.gif";
sessionGif = "root:/assets/kurukuru.gif";
wallpaperDir = "~/NixFlake/wallpapers";
};
services = {
audioIncrement = 0.1;
defaultPlayer = "MPD";
gpuType = "";
maxVolume = 1;
playerAliases = [
{
from = "com.github.th_ch.youtube_music";
to = "YT Music";
}
];
smartScheme = true;
useFahrenheit = false;
useTwelveHourClock = false;
visualiserBars = 45;
weatherLocation = "Dortmund, Germany";
};
session = {
commands = {
hibernate = ["systemctl" "hibernate"];
logout = ["loginctl" "terminate-user" ""];
reboot = ["systemctl" "reboot"];
shutdown = ["systemctl" "poweroff"];
};
dragThreshold = 30;
enabled = true;
vimKeybinds = false;
};
sidebar = {
dragThreshold = 80;
enabled = true;
};
utilities = {
enabled = true;
maxToasts = 4;
toasts = {
audioInputChanged = true;
audioOutputChanged = true;
capsLockChanged = true;
chargingChanged = true;
configLoaded = true;
dndChanged = true;
gameModeChanged = true;
kbLayoutChanged = false;
nowPlaying = false;
numLockChanged = true;
vpnChanged = true;
};
vpn = {
enabled = false;
provider = [
{
displayName = "Wireguard (Your VPN)";
interface = "your-connection-name";
name = "wireguard";
}
];
};
};
};
cli = {
enable = hyprland.caelestia.enable;
settings = {
record = {extraArgs = [];};
theme = {
enableBtop = false;
enableDiscord = false;
enableFuzzel = false;
enableGtk = false;
enableHypr = false;
enableQt = false;
enableSpicetify = false;
enableTerm = false;
};
toggles = {
communication = {
discord = {
command = ["discord"];
enable = false;
match = [{class = "discord";}];
move = true;
};
whatsapp = {
enable = false;
match = [{class = "whatsapp";}];
move = true;
};
};
music = {
feishin = {
enable = false;
match = [{class = "feishin";}];
move = true;
};
spotify = {
command = ["spicetify" "watch" "-s"];
enable = false;
match = [{class = "Spotify";} {initialTitle = "Spotify";} {initialTitle = "Spotify Free";}];
move = true;
};
};
sysmon = {
btop = {
command = ["kitty" "--title" "Btop" "-e" "btop"];
enable = false;
match = [
{
class = "btop";
title = "Btop";
workspace = {name = "special:sysmon";};
}
];
};
};
todo = {
todoist = {
command = ["todoist"];
enable = false;
match = [{class = "Todoist";}];
move = true;
};
};
};
wallpaper = {postHook = "echo $WALLPAPER_PATH";};
};
};
}

View File

@ -0,0 +1,180 @@
{
inputs,
config,
lib,
mylib,
pkgs,
nixosConfig,
username,
...
}: let
inherit (config.modules) hyprland color;
# Autostart programs
always-exec = import ./autostart.nix {inherit lib pkgs config hyprland;};
# Keybindings
always-bind = import ./mappings.nix {inherit lib config hyprland;};
# Mousebindings
always-bindm = {
"$mainMod, mouse:272" = ["movewindow"];
"$mainMod, mouse:273" = ["resizewindow"];
};
in {
options.modules.hyprland = import ./options.nix {inherit lib mylib;};
config = lib.mkIf hyprland.enable {
assertions = [
{
assertion = nixosConfig.programs.hyprland.enable;
message = "Can't enable Hyprland module with Hyprland disabled!";
}
{
assertion = builtins.hasAttr "hyprlock" nixosConfig.security.pam.services;
message = "Can't enable Hyprland module without Hyprlock PAM service!";
}
{
assertion = hyprland.hyprpanel.enable != hyprland.caelestia.enable;
message = "Can't enable Hyprpanel and Caelestia at the same time!";
}
];
gtk = {
enable = true;
iconTheme.package = lib.mkDefault color.iconPackage;
iconTheme.name = color.iconTheme;
};
modules = {
hyprpanel.enable = hyprland.hyprpanel.enable;
};
home = {
pointerCursor = {
gtk.enable = lib.mkDefault true;
x11.enable = lib.mkDefault true;
package = lib.mkDefault color.cursorPackage;
name = color.cursor;
size = color.cursorSize;
};
packages = with pkgs; [
hyprpaper # Wallpaper setter
hyprpicker # Color picker
# hyprpolkitagent # Ugly polkit authentication GUI
hyprland-qt-support
hyprsunset # Blue light filter
wl-clipboard
clipman # Clipboard manager (wl-paste)
libnotify
inotify-tools # Includes inotifywait
ncpamixer # Audio control
slurp # Region selector for screensharing
grim # Grab images from compositor
# Deps for Qt5 and Qt6 apps (e.g., Nextcloud)
qt5.qtwayland
qt6.qtwayland
];
file = {
".config/hypr/keybindings.info".text = let
fixupHomeDir = key:
builtins.replaceStrings ["/home/${username}"] ["~"] key;
fixupNixStore = key: let
# The pattern has to match the entire string, otherwise it won't work
matches = builtins.match ".*/nix/store/(.*)/.*" key;
in
if (matches == null)
then key
else builtins.replaceStrings matches ["..."] key;
fixupNoMod = key:
builtins.replaceStrings ["<-"] ["<"] key;
mkBindHelpKey = key:
builtins.replaceStrings ["$mainMod" " " ","] ["${hyprland.keybindings.main-mod}" "-" ""] key;
mkBindHelpAction = action:
builtins.replaceStrings [","] [""] action;
mkBindHelp = key: action: "<${mkBindHelpKey key}>: ${mkBindHelpAction action}";
mkBindsHelp = key: actions:
actions
|> builtins.map (mkBindHelp key)
|> builtins.map fixupNoMod
|> builtins.map fixupNixStore
|> builtins.map fixupHomeDir;
in
(hyprland.keybindings.bindings // always-bind)
|> builtins.mapAttrs mkBindsHelp
|> builtins.attrValues
|> builtins.concatLists
|> builtins.concatStringsSep "\n";
};
};
programs = {
hyprlock = import ./hyprlock.nix {inherit config hyprland color;};
caelestia = import ./caelestia.nix {inherit config hyprland color;};
};
services = {
dunst = import ./dunst.nix {inherit pkgs config hyprland color;};
hypridle = import ./hypridle.nix {inherit config hyprland color;};
hyprpaper = import ./hyprpaper.nix {inherit config hyprland color;};
};
# Make sure the units only start when using Hyprland
systemd.user.services.dunst.Unit.After = lib.mkIf hyprland.dunst.enable (lib.mkForce ["hyprland-session.target"]);
systemd.user.services.dunst.Unit.PartOf = lib.mkIf hyprland.dunst.enable (lib.mkForce ["hyprland-session.target"]);
systemd.user.services.hypridle.Install.WantedBy = lib.mkIf (!hyprland.caelestia.enable) (lib.mkForce ["hyprland-session.target"]);
systemd.user.services.hypridle.Unit.After = lib.mkIf (!hyprland.caelestia.enable) (lib.mkForce ["hyprland-session.target"]);
systemd.user.services.hypridle.Unit.PartOf = lib.mkIf (!hyprland.caelestia.enable) (lib.mkForce ["hyprland-session.target"]);
systemd.user.services.hyprpaper.Install.WantedBy = lib.mkIf (!hyprland.caelestia.enable) (lib.mkForce ["hyprland-session.target"]);
systemd.user.services.hyprpaper.Unit.After = lib.mkIf (!hyprland.caelestia.enable) (lib.mkForce ["hyprland-session.target"]);
systemd.user.services.hyprpaper.Unit.PartOf = lib.mkIf (!hyprland.caelestia.enable) (lib.mkForce ["hyprland-session.target"]);
wayland.windowManager.hyprland = {
enable = true;
package = inputs.hyprland.packages.${pkgs.stdenv.hostPlatform.system}.hyprland;
portalPackage = inputs.hyprland.packages.${pkgs.stdenv.hostPlatform.system}.xdg-desktop-portal-hyprland;
systemd.enable = true; # Enable hyprland-session.target
systemd.variables = ["--all"]; # Import PATH into systemd
xwayland.enable = true;
plugins = builtins.concatLists [
(lib.optionals
hyprland.bars.enable
[inputs.hyprland-plugins.packages.${pkgs.stdenv.hostPlatform.system}.hyprbars])
(lib.optionals
hyprland.dynamicCursor.enable
[inputs.hypr-dynamic-cursors.packages.${pkgs.stdenv.hostPlatform.system}.hypr-dynamic-cursors])
(lib.optionals
hyprland.trails.enable
[inputs.hyprland-plugins.packages.${pkgs.stdenv.hostPlatform.system}.hyprtrails])
(lib.optionals
hyprland.hyprspace.enable
[inputs.hyprspace.packages.${pkgs.stdenv.hostPlatform.system}.Hyprspace])
];
settings = import ./settings.nix {
inherit
lib
config
hyprland
color
always-exec
always-bind
always-bindm
;
};
};
};
}

View File

@ -0,0 +1,36 @@
{
pkgs,
config,
hyprland,
color,
}: {
enable = hyprland.dunst.enable;
iconTheme.package = color.iconPackage;
iconTheme.name = color.iconTheme;
settings = {
global = {
monitor = config.modules.waybar.monitor;
font = "${color.font} 11";
offset = "10x10";
background = color.hexS.base;
foreground = color.hexS.text;
frame_width = 2;
corner_radius = 6;
separator_color = "frame";
};
urgency_low = {
frame_color = color.hexS.green;
};
urgency_normal = {
frame_color = color.hexS.green;
};
urgency_critical = {
frame_color = color.hexS.red;
};
};
}

View File

@ -0,0 +1,28 @@
{
config,
hyprland,
color,
}: {
enable = !hyprland.caelestia.enable;
settings = {
general = {
# DPMS - Display Powermanagement Signaling. "On" means the monitor is on.
after_sleep_cmd = "hyprctl dispatch dpms on";
ignore_dbus_inhibit = false;
lock_cmd = "hyprlock";
};
listener = [
{
timeout = 900;
on-timeout = "hyprlock";
}
{
timeout = 1200;
on-timeout = "hyprctl dispatch dpms off";
on-resume = "hyprctl dispatch dpms on";
}
];
};
}

View File

@ -0,0 +1,74 @@
{
config,
hyprland,
color,
}: {
enable = true;
settings = {
general = {
disable_loading_bar = true;
grace = 0; # Immediately lock
hide_cursor = true;
no_fade_in = false;
};
# The widgets start here.
background = [
{
path = "${config.paths.nixflake}/wallpapers/${color.wallpaper}.jpg";
blur_passes = 3;
blur_size = 10;
monitor = "";
}
];
input-field = [
# Password input
{
size = "200, 50";
position = "0, 0";
monitor = "";
dots_center = true;
fade_on_empty = false;
font_color = "rgb(${color.hex.accentText})";
font_family = "${color.font}";
inner_color = "rgb(${color.hex.accent})";
outer_color = "rgb(${color.hex.accent})";
outline_thickness = 2;
placeholder_text = "<span foreground='\#\#${color.hex.accentText}'>Password...</span>";
shadow_passes = 0;
rounding = 4;
halign = "center";
valign = "center";
}
];
label = [
# Date
{
position = "0, 300";
monitor = "";
text = ''cmd[update:1000] date -I'';
color = "rgba(${color.hex.text}AA)";
font_size = 22;
font_family = "${color.font}";
halign = "center";
valign = "center";
}
# Time
{
position = "0, 200";
monitor = "";
text = ''cmd[update:1000] date +"%-H:%M"'';
color = "rgba(${color.hex.text}AA)";
font_size = 95;
font_family = "${color.font} Extrabold";
halign = "center";
valign = "center";
}
];
};
}

View File

@ -0,0 +1,28 @@
{
config,
hyprland,
color,
}: {
enable = !hyprland.caelestia.enable;
settings = {
ipc = "on";
splash = false;
splash_offset = 2.0;
# Wallpapers have to be preloaded to be displayed
preload = let
mkPreload = name: "${config.paths.nixflake}/wallpapers/${name}.jpg";
in
color.wallpapers |> builtins.map mkPreload;
wallpaper = let
mkWallpaper = monitor:
"${monitor}, "
+ "${config.paths.nixflake}/wallpapers/${color.wallpaper}.jpg";
in
hyprland.monitors
|> builtins.attrNames
|> builtins.map mkWallpaper;
};
}

View File

@ -0,0 +1,77 @@
{
lib,
config,
hyprland,
}:
lib.mergeAttrsList [
{
# Hyprland control
"$mainMod, q" = ["killactive"];
"$mainMod, v" = ["togglefloating"];
"$mainMod, f" = ["fullscreen"];
"$mainMod, tab" = ["workspace, previous"];
# "$mainMod, g" = ["togglegroup"];
# "ALT, tab" = ["changegroupactive"];
# Move focus with mainMod + arrow keys
"$mainMod, h" = ["movefocus, l"];
"$mainMod, l" = ["movefocus, r"];
"$mainMod, k" = ["movefocus, u"];
"$mainMod, j" = ["movefocus, d"];
# Swap windows
"$mainMod CTRL, h" = ["movewindow, l"];
"$mainMod CTRL, l" = ["movewindow, r"];
"$mainMod CTRL, k" = ["movewindow, u"];
"$mainMod CTRL, d" = ["movewindow, d"];
# Reset workspaces to the defined configuration in hyprland.workspaces:
"CTRL ALT, r" = let
mkWBinding = m: w:
"moveworkspacetomonitor, "
+ "${builtins.toString w} ${builtins.toString m}";
mkWsBindings = m: ws: builtins.map (mkWBinding m) ws;
in
hyprland.workspaces
|> builtins.mapAttrs mkWsBindings
|> builtins.attrValues
|> builtins.concatLists;
}
# Switch to WS: "$mainMod, 1" = ["workspace, 1"];
(let
mkWBinding = w: k: {"$mainMod, ${k}" = ["workspace, ${w}"];};
in
hyprland.keybindings.ws-bindings
|> builtins.mapAttrs mkWBinding
|> builtins.attrValues
|> lib.mergeAttrsList)
# Toggle special WS: "$mainMod, x" = ["togglespecialworkspace, ferdium"];
(let
mkSpecialWBinding = w: k: {"$mainMod, ${k}" = ["togglespecialworkspace, ${w}"];};
in
hyprland.keybindings.special-ws-bindings
|> builtins.mapAttrs mkSpecialWBinding
|> builtins.attrValues
|> lib.mergeAttrsList)
# Move to WS: "$mainMod SHIFT, 1" = ["movetoworkspace, 1"];
(let
mkMoveWBinding = w: k: {"$mainMod SHIFT, ${k}" = ["movetoworkspace, ${w}"];};
in
(hyprland.keybindings.ws-bindings)
|> builtins.mapAttrs mkMoveWBinding
|> builtins.attrValues
|> lib.mergeAttrsList)
# Move to special WS: "$mainMod SHIFT, x" = ["movetoworkspace, special:ferdium"];
(let
mkSpecialMoveWBinding = w: k: {"$mainMod SHIFT, ${k}" = ["movetoworkspace, special:${w}"];};
in
hyprland.keybindings.special-ws-bindings
|> builtins.mapAttrs mkSpecialMoveWBinding
|> builtins.attrValues
|> lib.mergeAttrsList)
]

View File

@ -0,0 +1,206 @@
{
lib,
mylib,
...
}: {
enable = lib.mkEnableOption "Hyprland Window Manager + Compositor";
dunst.enable = lib.mkEnableOption "Enable Dunst notification daemon";
bars.enable = lib.mkEnableOption "Enable window bars";
dynamicCursor.enable = lib.mkEnableOption "Enable dynamic cursors";
trails.enable = lib.mkEnableOption "Enable dynamic window trails";
hyprspace.enable = lib.mkEnableOption "Enable Hyprspace workspace overview";
hyprpanel.enable = lib.mkEnableOption "Enable Hyprpanel";
caelestia.enable = lib.mkEnableOption "Enable Caelestia";
keyboard = {
layout = lib.mkOption {
type = lib.types.str;
example = "us";
description = "Keyboard layout to use";
};
variant = lib.mkOption {
type = lib.types.str;
example = "altgr-intl";
description = "Keyboard layout variant";
};
option = lib.mkOption {
type = lib.types.str;
example = "nodeadkeys";
description = "Keyboard layout options";
};
};
keybindings = {
main-mod = lib.mkOption {
type = lib.types.str;
description = "Main modifier key";
example = ''
"SUPER"
'';
default = "SUPER";
};
bindings = lib.mkOption {
type = lib.types.attrsOf (lib.types.listOf lib.types.str);
description = "Hyprland keyboard shortcuts";
default = {};
example = ''
{
"CTRL ALT, R" = [
"moveworkspacetomonitor, 1 HDMI-A-1"
"moveworkspacetomonitor, 2 HDMI-A-1"
];
}
'';
};
ws-bindings = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
description = "Map keys to workspaces";
default = {};
example = ''
{
# "<Workspace>" = "<Key>";
"1" = "1";
"10" = "0";
}
'';
};
special-ws-bindings = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
description = "Map keys to special (scratchpad) workspaces";
default = {};
example = ''
{
# "<Workspace>" = "<Key>";
"ferdium" = "x";
"btop" = "b";
}
'';
};
};
monitors = lib.mkOption {
type = lib.types.attrs;
description = "Hyprland Monitor Configurations";
example = ''
{
"HDMI-A-1" = {
width = 2560;
height = 1440;
rate = 144;
x = 1920;
y = 0;
scale = 1;
}
}
'';
};
workspaces = lib.mkOption {
type = lib.types.attrs;
description = "How workspaces are distributed to monitors. These monitors will also receive a wallpaper.";
example = ''
{
"HDMI-A-1" = [1 2 3 4 5 6 7 8 9];
"HDMI-A-2" = [0];
}
'';
};
workspacerules = lib.mkOption {
type = lib.types.attrs;
description = "Launch programs on specified workspaces, accepts window class.";
example = ''
{
"2" = [
"jetbrains-clion"
"code-url-handler"
];
}
'';
};
windowrules = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = "Specify specific window rules.";
example = ''
[
"suppressevent activate, class: Unity"
]
'';
};
transparent-opacity = lib.mkOption {
type = lib.types.str;
description = "The opacity transparent windows should have.";
example = "0.8";
};
transparent = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = "What programs should be transparent? Accepts window class.";
example = ''
[
"kitty"
]
'';
};
floating = lib.mkOption {
type = lib.types.listOf lib.types.attrs;
description = "What programs are floating down here?";
example = ''
[
{
class = "thunar";
title = "File Operation Progress";
}
{
class = "org.kde.polkit-kde-authentication-agent-1";
}
]
'';
};
autostart = {
immediate = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = "Programs to launch when Hyprland starts";
example = ''
[
"kitty"
]
'';
default = [];
};
delayed = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = "Programs to launch with a delay when Hyprland starts (e.g. to wait for the waybar tray)";
example = ''
[
"keepassxc"
"nextcloud --background"
]
'';
default = [];
};
special-silent = lib.mkOption {
type = lib.types.attrsOf (lib.types.listOf lib.types.str);
description = "Programs to silently launch on special workspaces";
example = ''
{
"ferdium" = ["ferdium"];
"btop" = ["kitty --title=Btop btop"];
}
'';
default = {};
};
};
}

View File

@ -0,0 +1,359 @@
{
lib,
config,
hyprland,
color,
always-exec,
always-bind,
always-bindm,
}: {
"$mainMod" = "${hyprland.keybindings.main-mod}";
general = {
gaps_in = 5;
gaps_out = 10;
border_size = 2;
"col.active_border" = "rgb(${color.hex.accent})";
"col.inactive_border" = "rgb(${color.hex.base})";
};
group = {
groupbar = {
enabled = true;
render_titles = false;
font_size = 10;
gradients = false;
"col.active" = "rgb(${color.hex.accent})";
"col.inactive" = "rgb(${color.hex.base})";
};
"col.border_active" = "rgb(${color.hex.accent})";
"col.border_inactive" = "rgb(${color.hex.base})";
};
input = {
kb_layout = hyprland.keyboard.layout;
kb_variant = hyprland.keyboard.variant;
kb_options = hyprland.keyboard.option;
kb_model = "pc104";
kb_rules = "";
follow_mouse = true;
touchpad = {
natural_scroll = "no";
};
sensitivity = 0; # -1.0 - 1.0, 0 means no modification.
};
monitor = let
mkMonitor = name: conf:
"${name}, "
+ "${builtins.toString conf.width}x${builtins.toString conf.height}@"
+ "${builtins.toString conf.rate}, "
+ "${builtins.toString conf.x}x${builtins.toString conf.y}, "
+ "${builtins.toString conf.scale}";
in
hyprland.monitors
|> builtins.mapAttrs mkMonitor
|> builtins.attrValues;
workspace = let
mkWorkspace = monitor: workspace:
"${builtins.toString workspace}, "
+ "monitor:${builtins.toString monitor}";
mkWorkspaces = monitor: workspace-list:
builtins.map (mkWorkspace monitor) workspace-list;
in
hyprland.workspaces
|> builtins.mapAttrs mkWorkspaces
|> builtins.attrValues
|> builtins.concatLists;
bind = let
mkBind = key: action: "${key}, ${action}";
mkBinds = key: actions: builtins.map (mkBind key) actions;
in
(hyprland.keybindings.bindings // always-bind)
|> builtins.mapAttrs mkBinds
|> builtins.attrValues
|> builtins.concatLists;
bindm = let
mkBind = key: action: "${key}, ${action}";
mkBinds = key: actions: builtins.map (mkBind key) actions;
in
always-bindm
|> builtins.mapAttrs mkBinds
|> builtins.attrValues
|> builtins.concatLists;
exec-once = let
mkDelayedStart = str: ''hyprctl dispatch exec "sleep 5s && ${str}"'';
mkSpecialSilentStart = w: str: "[workspace special:${w} silent] ${str}";
mkSpecialSilentStarts = w: strs: builtins.map (mkSpecialSilentStart w) strs;
in
lib.mkMerge [
always-exec
hyprland.autostart.immediate
(hyprland.autostart.special-silent
|> builtins.mapAttrs mkSpecialSilentStarts
|> builtins.attrValues
|> builtins.concatLists)
(hyprland.autostart.delayed
|> builtins.map mkDelayedStart)
];
windowrule = let
mkWorkspaceRule = workspace: class:
"match:class ^(${class})$, "
+ "workspace ${workspace}";
mkWorkspaceRules = workspace: class-list:
builtins.map (mkWorkspaceRule workspace) class-list;
mkFloatingRule = attrs:
(lib.optionalString (builtins.hasAttr "class" attrs) "match:class ^(${attrs.class})$, ")
+ (lib.optionalString (builtins.hasAttr "title" attrs) "match:title ^(${attrs.title})$, ")
+ "float 1";
mkTranslucentRule = class:
"match:class ^(${class})$, "
+ "opacity ${hyprland.transparent-opacity} ${hyprland.transparent-opacity}";
in
lib.mkMerge [
(hyprland.workspacerules
|> builtins.mapAttrs mkWorkspaceRules
|> builtins.attrValues
|> builtins.concatLists)
(hyprland.floating
|> builtins.map mkFloatingRule)
(hyprland.transparent
|> builtins.map mkTranslucentRule)
hyprland.windowrules
];
dwindle = {
pseudotile = true;
preserve_split = true;
};
master = {
new_status = "master";
};
gesture = [
"3, horizontal, workspace" # 3 Fingers, horizontal, workspace swipe
];
misc = {
# Say no to the anime girl
disable_hyprland_logo = true;
force_default_wallpaper = 0;
# Say no to the "Application not responding" window
enable_anr_dialog = false;
disable_splash_rendering = true;
font_family = "${color.font}";
};
# Because those are not windows, but layers,
# we have to blur them explicitly
layerrule = [
"match:class rofi, blur 1"
# "match:class rofi, ignore_alpha 0.001" # Fix pixelated corners
# "match:class rofi, xray 0" # Render on top of other windows
# "match:class rofi, dim_around 1"
"match:class waybar, blur 1"
"match:class gtk4-layer-shell, blur 1"
"match:class bar-0, blur 1"
"match:class bar-1, blur 1"
];
decoration = {
rounding = 4;
shadow = {
enabled = false;
};
blur = {
enabled = true;
size = 10;
passes = 3;
new_optimizations = true;
ignore_opacity = true;
xray = true;
};
};
animations = {
enabled = true;
bezier = "myBezier, 0.05, 0.9, 0.1, 1.05";
animation = [
"windows, 1, 7, myBezier"
"windowsOut, 1, 7, default,popin 80%"
"border, 1, 10, default"
"borderangle, 1, 8, default"
"fade, 1, 7, default"
"workspaces, 1, 6, default"
];
};
plugin = lib.mergeAttrsList [
(lib.optionalAttrs hyprland.bars.enable {
hyprbars = {
enabled = true;
bar_height = 25;
bar_blur = true;
bar_color = "rgb(${color.hex.base})";
col.text = "rgb(${color.hex.text})";
bar_title_enabled = true;
bar_text_size = 12;
bar_text_font = color.font;
bar_text_align = "center";
bar_buttons_alignment = "left";
bar_part_of_window = true;
bar_precedence_over_border = false;
# example buttons (R -> L)
# hyprbars-button = color, size, on-click
hyprbars-button = [
"rgb(${color.hex.red}), 10, 󰖭, hyprctl dispatch killactive"
"rgb(${color.hex.green}), 10, , hyprctl dispatch fullscreen 1"
];
# cmd to run on double click of the bar
on_double_click = "hyprctl dispatch fullscreen 1";
};
})
(lib.optionalAttrs hyprland.dynamicCursor.enable {
dynamic-cursors = {
# enables the plugin
enabled = true;
# sets the cursor behaviour, supports these values:
# tilt - tilt the cursor based on x-velocity
# rotate - rotate the cursor based on movement direction
# stretch - stretch the cursor shape based on direction and velocity
# none - do not change the cursors behaviour
mode = "rotate";
# minimum angle difference in degrees after which the shape is changed
# smaller values are smoother, but more expensive for hw cursors
threshold = 2;
# for mode = rotate
rotate = {
# length in px of the simulated stick used to rotate the cursor
# most realistic if this is your actual cursor size
length = 20;
# clockwise offset applied to the angle in degrees
# this will apply to ALL shapes
offset = 0.0;
};
# for mode = tilt
tilt = {
# controls how powerful the tilt is, the lower, the more power
# this value controls at which speed (px/s) the full tilt is reached
# the full tilt being 60° in both directions
limit = 1000;
# relationship between speed and tilt, supports these values:
# linear - a linear function is used
# quadratic - a quadratic function is used (most realistic to actual air drag)
# negative_quadratic - negative version of the quadratic one, feels more aggressive
# see `activation` in `src/mode/utils.cpp` for how exactly the calculation is done
function = "negative_quadratic";
# time window (ms) over which the speed is calculated
# higher values will make slow motions smoother but more delayed
window = 100;
};
# configure shake to find
# magnifies the cursor if its is being shaken
shake = {
# enables shake to find
enabled = false;
# use nearest-neighbour (pixelated) scaling when shaking
# may look weird when effects are enabled
nearest = true;
# controls how soon a shake is detected
# lower values mean sooner
threshold = 3.0;
# magnification level immediately after shake start
base = 1.5;
# magnification increase per second when continuing to shake
speed = 0.0;
# how much the speed is influenced by the current shake intensitiy
influence = 0.0;
# maximal magnification the cursor can reach
# values below 1 disable the limit (e.g. 0)
limit = 0.0;
# time in millseconds the cursor will stay magnified after a shake has ended
timeout = 1000;
# show cursor behaviour `tilt`, `rotate`, etc. while shaking
effects = true;
# enable ipc events for shake
# see the `ipc` section below
ipc = false;
};
# use hyprcursor to get a higher resolution texture when the cursor is magnified
# see the `hyprcursor` section below
hyprcursor = {
# use nearest-neighbour (pixelated) scaling when magnifing beyond texture size
# this will also have effect without hyprcursor support being enabled
# 0 / false - never use pixelated scaling
# 1 / true - use pixelated when no highres image
# 2 - always use pixleated scaling
nearest = true;
# enable dedicated hyprcursor support
enabled = true;
# resolution in pixels to load the magnified shapes at
# be warned that loading a very high-resolution image will take a long time and might impact memory consumption
# -1 means we use [normal cursor size] * [shake:base option]
resolution = -1;
# shape to use when clientside cursors are being magnified
# see the shape-name property of shape rules for possible names
# specifying clientside will use the actual shape, but will be pixelated
fallback = "clientside";
};
};
})
(lib.optionalAttrs hyprland.trails.enable {
hyprtrails = {
color = "rgb(${color.hex.accent})";
};
})
(lib.optionalAttrs hyprland.hyprspace.enable {
overview = {};
})
];
}

View File

@ -0,0 +1,342 @@
{
config,
nixosConfig,
lib,
mylib,
pkgs,
...
}: let
inherit (config.modules) hyprpanel color;
in {
options.modules.hyprpanel = import ./options.nix {inherit lib mylib;};
config = lib.mkIf hyprpanel.enable {
programs.hyprpanel = {
enable = true;
systemd.enable = hyprpanel.systemd.enable;
settings = {
#
# Bar Config
#
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/config/index.ts
"scalingPriority" = "hyprland";
"wallpaper.enable" = false;
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/config/bar/index.ts
"bar.autoHide" = "never";
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/config/bar/layouts/index.ts
# TODO: To module option
# TODO: This should contain battery etc. for laptop
"bar.layouts" = {
"DP-1" = {
"left" = ["workspaces" "windowtitle"];
"middle" = ["media"]; # "cava"
"right" = ["volume" "network" "cpu" "ram" "storage" "clock" "systray" "notifications"]; # "bluetooth"
};
"DP-2" = {
"left" = ["workspaces" "windowtitle"];
"middle" = ["media"]; # "cava"
"right" = ["volume" "clock" "notifications"];
};
};
# TODO: Expose this as a module option: applicationIcons = {kitty = "󰄛"; ...};
"bar.workspaces.applicationIconMap" = {
"class:^(kitty)$" = "󰄛";
"class:^(org\.keepassxc\.KeePassXC)$" = "󰟵";
"class:^(com\.nextcloud\.desktopclient\.nextcloud)$" = "";
"class:^(neovide)$" = "";
"class:^(jetbrains-clion)$" = "";
"class:^(jetbrains-idea)$" = "";
"class:^(jetbrains-pycharm)$" = "";
"class:^(jetbrains-rustrover)$" = "";
"class:^(jetbrains-rider)$" = "";
"class:^(jetbrains-webstorm)$" = "";
"class:^(obsidian)$" = "";
"class:^(anki)$" = "";
"class:^(blender)$" = "󰂫";
"class:^(unityhub)$" = "";
"class:^(Unity)$" = "";
"class:^(steam)$" = "";
"class:^(steam_app_)(.+)$" = "";
"class:^(signal)$" = "󱋊";
"class:^(Spotify)$" = "";
"class:^(rmpc)$" = "󰝚";
"class:^(discord)$" = "";
"class:^(Zotero)$" = "";
"class:^(org.zealdocs.zeal)$" = "󰞋";
"class:^(navi)$" = "";
"class:^(org.qutebrowser.qutebrowser)$" = "󰖟";
};
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/theme/bar/index.ts
"theme.bar.background" = "#${color.hex.base}";
"theme.bar.border.color" = "#${color.hex.accent}";
"theme.bar.border.location" = "full";
"theme.bar.border_radius" = "6px";
"theme.bar.border.width" = "2px";
"theme.bar.dropdownGap" = "50px";
"theme.bar.floating" = true;
"theme.bar.label_spacing" = "0px"; # what does this do?
"theme.bar.margin_bottom" = "0px";
"theme.bar.margin_sides" = "10px";
"theme.bar.margin_top" = "10px";
"theme.bar.opacity" = 75;
"theme.bar.outer_spacing" = "0px"; # NOTE: Left/Right bar padding
"theme.bar.transparent" = false;
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/theme/bar/buttons/index.ts
"theme.bar.buttons.opacity" = 100;
"theme.bar.buttons.padding_x" = "10px";
"theme.bar.buttons.padding_y" = "2px";
"theme.bar.buttons.radius" = "3px";
"theme.bar.buttons.spacing" = "2px"; # NOTE: Horizontal inter-button spacing
"theme.bar.buttons.style" = "default";
"theme.bar.buttons.text" = "#${color.hex.accentText}";
"theme.bar.buttons.y_margins" = "2px"; # NOTE: Top/Bottom bar padding
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/theme/general/index.ts
"theme.font.label" = color.font;
"theme.font.name" = color.font;
"theme.font.size" = "14px";
"theme.font.weight" = 600;
#
# Modules Config
#
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/config/bar/workspaces/index.ts
"bar.workspaces.applicationIconEmptyWorkspace" = "";
"bar.workspaces.applicationIconFallback" = "󰣆";
"bar.workspaces.applicationIconOncePerWorkspace" = true;
"bar.workspaces.ignored" = "-\\d+"; # Special workspaces
"bar.workspaces.monitorSpecific" = true;
"bar.workspaces.numbered_active_indicator" = "highlight";
"bar.workspaces.reverse_scroll" = true;
"bar.workspaces.show_icons" = false;
"bar.workspaces.show_numbered" = false;
"bar.workspaces.showAllActive" = true;
"bar.workspaces.showApplicationIcons" = true; # requires showWsIcons
"bar.workspaces.showWsIcons" = true;
# "bar.workspaces.spacing" = 1;
"bar.workspaces.workspaces" = 9;
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/theme/bar/buttons/workspaces.ts
"theme.bar.buttons.workspaces.active" = "#${color.hex.accentHl}";
"theme.bar.buttons.workspaces.available" = "#${color.hex.accentText}";
"theme.bar.buttons.workspaces.background" = "#${color.hex.accent}";
"theme.bar.buttons.workspaces.border" = "#${color.hex.accent}";
"theme.bar.buttons.workspaces.enableBorder" = false;
"theme.bar.buttons.workspaces.fontSize" = "18px";
"theme.bar.buttons.workspaces.hover" = "#${color.hex.accentHl}";
"theme.bar.buttons.workspaces.numbered_active_highlight_border" = "4px"; # border radius
"theme.bar.buttons.workspaces.numbered_active_highlighted_text_color" = "#${color.hex.accentText}";
"theme.bar.buttons.workspaces.numbered_active_highlight_padding" = "6px";
"theme.bar.buttons.workspaces.numbered_active_underline_color" = "#${color.hex.accentHl}";
"theme.bar.buttons.workspaces.numbered_inactive_padding" = "6px"; # make the same as numbered_active_highlight_padding to avoid layout jumping
"theme.bar.buttons.workspaces.occupied" = "#${color.hex.accentText}";
"theme.bar.buttons.workspaces.smartHighlight" = "false";
"theme.bar.buttons.workspaces.spacing" = "6px"; # no visible difference?
# The pill marks the active workspace when icons are disabled
# "theme.bar.buttons.workspaces.pill" = {
# "active_width" = "12em";
# "height" = "4em";
# "radius" = "4px";
# "width" = "4em";
# };
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/config/bar/windowtitle/index.ts
"bar.windowtitle.class_name" = true;
"bar.windowtitle.custom_title" = true;
"bar.windowtitle.icon" = true;
"bar.windowtitle.label" = true;
"bar.windowtitle.truncation" = true;
"bar.windowtitle.truncation_size" = 50;
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/theme/bar/buttons/windowtitle.ts
"theme.bar.buttons.windowtitle.background" = "#${color.hex.pink}";
"theme.bar.buttons.windowtitle.border" = "#${color.hex.accent}";
"theme.bar.buttons.windowtitle.enableBorder" = false;
"theme.bar.buttons.windowtitle.icon_background" = "#${color.hex.pink}";
"theme.bar.buttons.windowtitle.icon" = "#${color.hex.accentText}";
"theme.bar.buttons.windowtitle.spacing" = "6px"; # Spacing between icon and text
"theme.bar.buttons.windowtitle.text" = "#${color.hex.accentText}";
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/config/bar/media/index.ts
"bar.media.format" = "{artist: - }{title}";
"bar.media.show_active_only" = true;
"bar.media.show_label" = true;
"bar.media.truncation" = true;
"bar.media.truncation_size" = 30;
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/theme/bar/buttons/media.ts
"theme.bar.buttons.media.background" = "#${color.hex.lavender}";
"theme.bar.buttons.media.border" = "#${color.hex.accent}";
"theme.bar.buttons.media.enableBorder" = false;
"theme.bar.buttons.media.icon_background" = "#${color.hex.lavender}";
"theme.bar.buttons.media.icon" = "#${color.hex.accentText}";
"theme.bar.buttons.media.spacing" = "6px";
"theme.bar.buttons.media.text" = "#${color.hex.accentText}";
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/config/bar/cava/index.ts
"bar.customModules.cava.showActiveOnly" = true;
"bar.customModules.cava.bars" = 10;
# "bar.customModules.cava.leftClick" = "menu:media";
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/theme/bar/buttons/cava.ts
"theme.bar.buttons.modules.cava.background" = "#${color.hex.red}";
"theme.bar.buttons.modules.cava.border" = "#${color.hex.accent}";
"theme.bar.buttons.modules.cava.enableBorder" = false;
"theme.bar.buttons.modules.cava.icon" = "#${color.hex.accentText}";
"theme.bar.buttons.modules.cava.icon_background" = "#${color.hex.red}";
"theme.bar.buttons.modules.cava.spacing" = "6px";
"theme.bar.buttons.modules.cava.text" = "#${color.hex.accentText}";
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/config/bar/volume/index.ts
"bar.volume.middleClick" = "kitty ncpamixer";
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/theme/bar/buttons/volume.ts
"theme.bar.buttons.volume.background" = "#${color.hex.maroon}";
"theme.bar.buttons.volume.enableBorder" = false;
"theme.bar.buttons.volume.border" = "#${color.hex.accent}";
"theme.bar.buttons.volume.icon_background" = "#${color.hex.maroon}";
"theme.bar.buttons.volume.icon" = "#${color.hex.accentText}";
"theme.bar.buttons.volume.spacing" = "6px";
"theme.bar.buttons.volume.text" = "#${color.hex.accentText}";
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/config/bar/network/index.ts
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/theme/bar/buttons/network.ts
"theme.bar.buttons.network.background" = "#${color.hex.peach}";
"theme.bar.buttons.network.enableBorder" = false;
"theme.bar.buttons.network.border" = "#${color.hex.accent}";
"theme.bar.buttons.network.icon_background" = "#${color.hex.peach}";
"theme.bar.buttons.network.icon" = "#${color.hex.accentText}";
"theme.bar.buttons.network.spacing" = "6px";
"theme.bar.buttons.network.text" = "#${color.hex.accentText}";
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/config/bar/bluetooth/index.ts
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/theme/bar/buttons/bluetooth.ts
"theme.bar.buttons.bluetooth.background" = "#${color.hex.yellow}";
"theme.bar.buttons.bluetooth.enableBorder" = false;
"theme.bar.buttons.bluetooth.border" = "#${color.hex.accent}";
"theme.bar.buttons.bluetooth.icon_background" = "#${color.hex.yellow}";
"theme.bar.buttons.bluetooth.icon" = "#${color.hex.accentText}";
"theme.bar.buttons.bluetooth.spacing" = "6px";
"theme.bar.buttons.bluetooth.text" = "#${color.hex.accentText}";
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/config/bar/cpu/index.ts
"bar.customModules.cpu.middleClick" = "kitty btop";
"bar.customModules.cpu.pollingInterval" = 1000;
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/theme/bar/buttons/cpu.ts
"theme.bar.buttons.modules.cpu.background" = "#${color.hex.green}";
"theme.bar.buttons.modules.cpu.enableBorder" = false;
"theme.bar.buttons.modules.cpu.border" = "#${color.hex.accent}";
"theme.bar.buttons.modules.cpu.icon_background" = "#${color.hex.green}";
"theme.bar.buttons.modules.cpu.icon" = "#${color.hex.accentText}";
"theme.bar.buttons.modules.cpu.spacing" = "6px";
"theme.bar.buttons.modules.cpu.text" = "#${color.hex.accentText}";
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/config/bar/ram/index.ts
"bar.customModules.ram.labelType" = "percentage"; # "used/total", "percentage"
"bar.customModules.ram.pollingInterval" = 1000;
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/theme/bar/buttons/ram.ts
"theme.bar.buttons.modules.ram.background" = "#${color.hex.teal}";
"theme.bar.buttons.modules.ram.enableBorder" = false;
"theme.bar.buttons.modules.ram.border" = "#${color.hex.accent}";
"theme.bar.buttons.modules.ram.icon_background" = "#${color.hex.teal}";
"theme.bar.buttons.modules.ram.icon" = "#${color.hex.accentText}";
"theme.bar.buttons.modules.ram.spacing" = "6px";
"theme.bar.buttons.modules.ram.text" = "#${color.hex.accentText}";
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/config/bar/storage/index.ts
"bar.customModules.storage.labelType" = "percentage"; # "used/total", "percentage"
"bar.customModules.storage.tooltipStyle" = "simple"; # "tree", "percentage-bar", "simple"
"bar.customModules.storage.pollingInterval" = 60000;
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/theme/bar/buttons/storage.ts
"theme.bar.buttons.modules.storage.background" = "#${color.hex.sky}";
"theme.bar.buttons.modules.storage.enableBorder" = false;
"theme.bar.buttons.modules.storage.border" = "#${color.hex.accent}";
"theme.bar.buttons.modules.storage.icon_background" = "#${color.hex.sky}";
"theme.bar.buttons.modules.storage.icon" = "#${color.hex.accentText}";
"theme.bar.buttons.modules.storage.spacing" = "6px";
"theme.bar.buttons.modules.storage.text" = "#${color.hex.accentText}";
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/config/bar/clock/index.ts
"bar.clock.format" = "%Y-%m-%d %H:%M";
"bar.clock.showTime" = true;
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/theme/bar/buttons/clock.ts
"theme.bar.buttons.clock.background" = "#${color.hex.sapphire}";
"theme.bar.buttons.clock.enableBorder" = false;
"theme.bar.buttons.clock.border" = "#${color.hex.accent}";
"theme.bar.buttons.clock.icon_background" = "#${color.hex.sapphire}";
"theme.bar.buttons.clock.icon" = "#${color.hex.accentText}";
"theme.bar.buttons.clock.spacing" = "6px";
"theme.bar.buttons.clock.text" = "#${color.hex.accentText}";
# TODO: To module option
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/config/bar/systray/index.ts
"bar.systray.ignore" = [
"Fcitx" # Keyboard indicator
]; # Middle click the tray icon to show a notification with the app name :)
"bar.systray.customIcons" = {};
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/theme/bar/buttons/systray.ts
"theme.bar.buttons.systray.background" = "#${color.hex.blue}";
"theme.bar.buttons.systray.enableBorder" = false;
"theme.bar.buttons.systray.border" = "#${color.hex.accent}";
"theme.bar.buttons.systray.customIcon" = "#${color.hex.accentText}";
"theme.bar.buttons.systray.spacing" = "6px";
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/config/bar/notifications/index.ts
"bar.notifications.hideCountWhenZero" = true;
"bar.notifications.show_total" = true;
# https://github.com/Jas-SinghFSU/HyprPanel/blob/master/src/configuration/modules/theme/bar/buttons/notifications.ts
"theme.bar.buttons.notifications.background" = "#${color.hex.accent}";
"theme.bar.buttons.notifications.enableBorder" = false;
"theme.bar.buttons.notifications.border" = "#${color.hex.accent}";
"theme.bar.buttons.notifications.icon_background" = "#${color.hex.accent}";
"theme.bar.buttons.notifications.icon" = "#${color.hex.accentText}";
"theme.bar.buttons.notifications.spacing" = "6px";
"theme.bar.buttons.notifications.total" = "#${color.hex.accentText}";
#
# TODO: Menus Config
#
"theme.bar.menus.background" = "#${color.hex.base}";
"theme.bar.menus.border.color" = "#${color.hex.accent}";
"theme.bar.menus.border.radius" = "6px";
"theme.bar.menus.border.size" = "2px";
"theme.bar.menus.buttons.radius" = "0.4em";
"theme.bar.menus.card_radius" = "0.4em";
"menus.clock.time.military" = true;
"menus.clock.weather.location" = "Dortmund";
"menus.clock.weather.key" = "1d22720b9e0848a9b1303412251706"; # Don't care if public
"menus.clock.weather.unit" = "metric";
"menus.transition" = "crossfade";
"menus.transitionTime" = 200;
#
# TODO: Notifications Config
#
"notifications.position" = "top right";
"notifications.showActionsOnHover" = true;
"notifications.timeout" = 5000;
};
};
};
}

View File

@ -0,0 +1,10 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "Enable Hyprpanel";
systemd.enable = mkEnableOption "Start using systemd";
}

View File

@ -0,0 +1,122 @@
# TODO: Expose some settings
{
config,
lib,
mylib,
...
}: let
inherit (config.modules) kitty color;
in {
options.modules.kitty = import ./options.nix {inherit lib mylib;};
config = lib.mkIf kitty.enable {
programs.kitty = {
enable = true;
shellIntegration.enableFishIntegration = true;
font = {
name = "${config.modules.color.font}";
size = 12;
};
keybindings = {
"kitty_mod" = "ctrl+shift";
"kitty_mod+enter" = "launch --cwd=current";
"kitty_mod+j" = "next_window";
"kitty_mod+k" = "previous_window";
"kitty_mod+l" = "next_layout";
};
settings = {
editor = config.home.sessionVariables.EDITOR;
scrollback_lines = 10000;
window_padding_width = 10; # Looks stupid with editors if bg doesn't match
# hide_window_decorations = "yes";
enabled_layouts = "grid,vertical,horizontal";
allow_remote_control = "yes"; # For nnn file preview or nvim scrollback
listen_on = "unix:@mykitty";
tab_bar_min_tabs = 2; # Don't show a single tab
tab_bar_edge = "bottom";
tab_bar_style = "powerline";
tab_powerline_style = "round";
tab_title_template = "{title}{' :{}:'.format(num_windows) if num_windows > 1 else ''}";
#
# Color Theme
#
# The basic colors
background = color.hexS.base;
foreground = color.hexS.text;
selection_foreground = color.hexS.base;
selection_background = color.hexS.rosewater;
# Cursor colors
cursor = color.hexS.rosewater;
cursor_text_color = color.hexS.base;
# URL underline color when hovering with mouse
url_color = color.hexS.rosewater;
# Kitty window border colors
active_border_color = color.hexS.lavender;
inactive_border_color = color.hexS.overlay0;
bell_border_color = color.hexS.yellow;
# OS Window titlebar colors
wayland_titlebar_color = "system";
macos_titlebar_color = "system";
# Tab bar colors
active_tab_foreground = color.hexS.base;
active_tab_background = color.hexS.lavender;
inactive_tab_foreground = color.hexS.text;
inactive_tab_background = color.hexS.crust;
tab_bar_background = color.hexS.base;
# Color for marks (marked text in the terminal)
mark1_foreground = color.hexS.base;
mark1_background = color.hexS.lavender;
mark2_foreground = color.hexS.base;
mark2_background = color.hexS.mauve;
mark3_foreground = color.hexS.base;
mark3_background = color.hexS.sapphire;
# The 16 terminal colors
# black
color0 = color.hexS.subtext1;
color8 = color.hexS.subtext0;
# red
color1 = color.hexS.red;
color9 = color.hexS.red;
# green
color2 = color.hexS.green;
color10 = color.hexS.green;
# yellow
color3 = color.hexS.yellow;
color11 = color.hexS.yellow;
# blue
color4 = color.hexS.blue;
color12 = color.hexS.blue;
# magenta
color5 = color.hexS.pink;
color13 = color.hexS.pink;
# cyan
color6 = color.hexS.teal;
color14 = color.hexS.teal;
# white
color7 = color.hexS.surface2;
color15 = color.hexS.surface1;
};
};
};
}

View File

@ -0,0 +1,9 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "Kitty";
}

View File

@ -0,0 +1,54 @@
{
config,
nixosConfig,
lib,
mylib,
pkgs,
...
}: let
inherit (config.modules) lazygit color;
in {
options.modules.lazygit = import ./options.nix {inherit lib mylib;};
config = lib.mkIf lazygit.enable {
programs.lazygit = {
enable = true;
settings = {
notARepository = "quit";
timeFormat = "2022-12-31";
shortTimeFormat = "23:49";
border = "rounded";
update.method = "never";
git = {
overrideGpg = true; # Allow editing past signed commits
branchLogCmd = "git log --all --graph --pretty=format:'%C(magenta)%h %C(white) %an %ar%C(auto) %D%n%s%n'";
parseEmoji = true;
};
gui = {
nerdFontsVersion = "3"; # Show icons
theme = {
lightTheme = false;
activeBorderColor = [color.hexS.accent "bold"];
inactiveBorderColor = [color.hexS.overlay0];
defaultFgColor = [color.hexS.text];
optionsTextColor = [color.hexS.accentDim];
# Because we can't set the fucking foregrounds for this, use a dark color
selectedLineBgColor = [color.hexS.surface0];
selectedRangeBgColor = [color.hexS.surface0];
cherryPickedCommitBgColor = [color.hexS.green];
cherryPickedCommitFgColor = [color.hexS.blue];
unstagedChangeColor = [color.hexS.red];
};
};
};
};
};
}

View File

@ -0,0 +1,7 @@
{
lib,
mylib,
...
}: {
enable = lib.mkEnableOption "Enable lazygit";
}

View File

@ -0,0 +1,93 @@
{
config,
nixosConfig,
lib,
mylib,
pkgs,
...
}: let
inherit (config.modules) mpd;
in {
options.modules.mpd = import ./options.nix {inherit lib mylib;};
config = lib.mkIf mpd.enable {
services = {
mpd = {
enable = true;
dataDir = "${config.home.homeDirectory}/Music/.mpd";
musicDirectory = "${config.home.homeDirectory}/Music";
network = {
listenAddress = "127.0.0.1"; # Listen on all addresses: "any"
port = 6600;
};
extraArgs = ["--verbose"];
extraConfig = ''
# Refresh the database whenever files in the musicDirectory change
auto_update "yes"
# Don't start playback after startup
restore_paused "yes"
# Use track tags on shuffle and album tags on album play (auto)
# Use album's tags (album)
# Use track's tags (track)
# replaygain "auto"
# PipeWire main output
audio_output {
type "pipewire"
name "PipeWire Sound Server"
# Use hardware mixer instead of software volume filter
# Alternative: replaygain_handler "software"
# mixer_type "hardware"
# replay_gain_handler "mixer"
}
# FiFo output for cava visualization
audio_output {
type "fifo"
name "my_fifo"
path "/tmp/mpd.fifo"
format "44100:16:2"
}
# Pre-cache 1GB of the queue
# input_cache {
# size "1 GB"
# }
# If mpd should follow symlinks pointing outside the musicDirectory
# follow_outside_symlinks "no"
# If mpd should follow symlinks pointing inside the musicDirectory
# follow_inside_symlinks "yes"
'';
};
# MPD integration with mpris (used by player-ctl).
# We want to use mpris as it also supports other players (e.g. Spotify) or browsers.
mpd-mpris = {
enable = true;
mpd.useLocal = true;
};
mpd-discord-rpc = {
# NOTE: Creates a new thread for each IPC request but don't cleans them up?
# They just keep accumulating when discord is not running lol
enable = false;
# NOTE: Bitch wants to create a default config file inside a
# read-only filesystem when changing settings here...
# settings = {
# hosts = "127.0.0.1:${builtins.toString config.services.mpd.network.port}";
# format = {
# details = "$title";
# state = "On $album by $artist";
# };
# };
};
};
};
}

View File

@ -0,0 +1,7 @@
{
lib,
mylib,
...
}: {
enable = lib.mkEnableOption "Enable the Music Player Daemon";
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,68 @@
-- Make Lazy window border rounded
require("lazy.core.config").options.ui.border = "rounded"
-- Disable rocks. For some reason, we still have to activate
-- "Install" in the Lazy menu once to disable rocks completely.
require("lazy.core.config").options.rocks.enabled = false
-- Default filetype to tex instead of plaintex
vim.g.tex_flavor = "latex"
-- Toggle inline diagnostics and show border
vim.g.enable_inline_diagnostics = false
vim.diagnostic.config({
virtual_text = vim.g.enable_inline_diagnostics,
float = { border = "rounded" },
})
vim.api.nvim_create_user_command("ToggleInlineDiagnostics", function()
vim.g.enable_inline_diagnostics = not vim.g.enable_inline_diagnostics
vim.diagnostic.config({ virtual_text = vim.g.enable_inline_diagnostics, float = { border = "rounded" } })
vim.notify((vim.g.enable_inline_diagnostics and "Enabled" or "Disabled") .. " inline diagnostics")
end, {
desc = "Toggle inline diagnostics",
})
-- Toggle conform format_on_save
vim.g.disable_autoformat = false
vim.api.nvim_create_user_command("ToggleAutoformat", function()
vim.g.disable_autoformat = not vim.g.disable_autoformat
vim.notify((vim.g.disable_autoformat and "Disabled" or "Enabled") .. " autoformat-on-save")
end, {
desc = "Toggle autoformat-on-save",
})
-- Allow navigating popupmenu completion with Up/Down
vim.api.nvim_set_keymap("c", "<Down>", 'v:lua.get_wildmenu_key("<right>", "<down>")', { expr = true })
vim.api.nvim_set_keymap("c", "<Up>", 'v:lua.get_wildmenu_key("<left>", "<up>")', { expr = true })
function _G.get_wildmenu_key(key_wildmenu, key_regular)
return vim.fn.wildmenumode() ~= 0 and key_wildmenu or key_regular
end
-- Check LSP server config
vim.api.nvim_create_user_command("LspInspect", function()
vim.notify(vim.inspect(vim.lsp.get_active_clients()))
end, {
desc = "Print LSP server configuration",
})
-- Toggle linting
vim.g.disable_autolint = false
vim.api.nvim_create_user_command("ToggleAutoLint", function()
vim.g.disable_autolint = not vim.g.disable_autolint
if vim.g.disable_autolint then
-- vim.diagnostic.reset(vim.api.nvim_get_current_buf())
vim.diagnostic.reset() -- Reset for all buffers
end
vim.notify((vim.g.disable_autolint and "Disabled" or "Enabled") .. " autolint-on-save")
end, {
desc = "Toggle autolint-on-save",
})
-- Toggle Rmpc
local Terminal = require("toggleterm.terminal").Terminal
local rmpc =
Terminal:new({ cmd = "rmpc", hidden = true, close_on_exit = true, auto_scroll = false, direction = "float" })
vim.g.toggle_rmpc = function()
rmpc:toggle()
end

View File

@ -0,0 +1,26 @@
local opt = vim.opt
local g = vim.g
local o = vim.o
-- Neovide
if g.neovide then
-- require("notify").notify("Running in NeoVide")
g.neovide_cursor_animate_command_line = true
g.neovide_cursor_animate_in_insert_mode = true
-- g.neovide_fullscreen = false
g.neovide_hide_mouse_when_typing = true
g.neovide_padding_top = 0
g.neovide_padding_bottom = 0
g.neovide_padding_right = 0
g.neovide_padding_left = 0
g.neovide_refresh_rate = 165
g.neovide_floating_corner_radius = 0.0
-- g.neovide_theme = "light"
-- Neovide Fonts
-- o.guifont = "JetBrainsMono Nerd Font Mono:h12:Medium"
o.guifont = "MonoLisa Alt Script:h12:Medium"
else
-- require("notify").notify("Not running in NeoVide")
end

View File

@ -0,0 +1,970 @@
_: let
# TODO: Doesn't work reliably. I think they are rebound by plugins after? Try setting in extraConfigLuaPost...
disabled-mappings = let
mkDisabledMapping = mapping: {
mode = ["n" "v"];
key = mapping;
action = "<Nop>";
};
disableMappings = [
# I only use f/F with flash
"s"
"S"
"t"
"T"
"H"
"L"
# Use flash to repeat f/F instead of ;/,
# ;/, are now free for localleader and exiting visual mode like helix
","
";"
# Use Telescope on "/", I don't want backwards search
"?"
];
in
builtins.map mkDisabledMapping disableMappings;
no-leader = [
# Cursor movement
{
mode = "n";
key = "j";
action = "v:count == 0 ? 'gj' : 'j'";
options.desc = "Move Cursor Down";
options.expr = true;
}
{
mode = "n";
key = "<Down>";
action = "v:count == 0 ? 'gj' : 'j'";
options.desc = "Move Cursor Down";
options.expr = true;
}
{
mode = "n";
key = "k";
action = "v:count == 0 ? 'gk' : 'k'";
options.desc = "Move Cursor Up";
options.expr = true;
}
{
mode = "n";
key = "<Up>";
action = "v:count == 0 ? 'gk' : 'k'";
options.desc = "Move Cursor Up";
options.expr = true;
}
{
mode = "n";
key = "H";
action = "^";
options.desc = "Move Cursor to Line Start";
}
{
mode = "n";
key = "L";
action = "$";
options.desc = "Move Cursor to Line End";
}
# Window resize
{
mode = "n";
key = "<C-h>";
action = "<cmd>vertical resize -2<cr>";
options.desc = "Decrease Window Width";
}
{
mode = "n";
key = "<C-l>";
action = "<cmd>vertical resize +2<cr>";
options.desc = "Increase Window Width";
}
{
mode = "n";
key = "<C-j>";
action = "<cmd>resize -2<cr>";
options.desc = "Decrease Window Height";
}
{
mode = "n";
key = "<C-k>";
action = "<cmd>resize +2<cr>";
options.desc = "Increase Window Height";
}
# Move lines
{
mode = "n";
key = "<M-j>";
action = "<cmd>m .+1<cr>==";
options.desc = "Move Line Down";
}
{
mode = "i";
key = "<M-j>";
action = "<Esc><cmd>m .+1<cr>==gi";
options.desc = "Move Line Down";
}
{
mode = "v";
key = "<M-j>";
action = ":m '>+1<cr>gv=gv";
options.desc = "Move Line Down";
}
{
mode = "n";
key = "<M-k>";
action = "<cmd>m .-2<cr>==";
options.desc = "Move Line Up";
}
{
mode = "i";
key = "<M-k>";
action = "<Esc><cmd>m .-2<cr>==gi";
options.desc = "Move Line Up";
}
{
mode = "v";
key = "<M-k>";
action = ":m '<-2<cr>gv=gv";
options.desc = "Move Line Up";
}
# Save buffers
{
mode = ["n" "i" "v"];
key = "<C-s>";
action = "<cmd>w<cr>";
options.desc = "Save Buffer";
}
{
mode = ["n" "i" "v"];
key = "<C-S-s>";
action = "<cmd>wa<cr>";
options.desc = "Save All Buffers";
}
# Indentation
{
mode = "v";
key = "<";
action = "<gv";
options.desc = "Outdent";
}
{
mode = "n";
key = "<";
action = "v<<Esc>";
options.desc = "Outdent";
}
{
mode = "v";
key = ">";
action = ">gv";
options.desc = "Indent";
}
{
mode = "n";
key = ">";
action = "v><Esc>";
options.desc = "Indent";
}
{
mode = "i";
key = "<Tab>";
action = "<cmd>lua require('intellitab').indent()<cr>";
options.desc = "Indent (IntelliTab)";
}
# Centered jumping
{
mode = "n";
key = "<C-d>";
action = "<C-d>zz";
options.desc = "Jump Down (Centered)";
}
{
mode = "n";
key = "<C-u>";
action = "<C-u>zz";
options.desc = "Jump Up (Centered)";
}
{
mode = "n";
key = "n";
action = "nzzzv";
options.desc = "Next Match (Centered)";
}
{
mode = "n";
key = "N";
action = "Nzzzv";
options.desc = "Previous Match (Centered)";
}
# Delete word
{
mode = "i";
key = "<C-BS>";
action = "<C-w>";
options.desc = "Delete Previous Word"; # TODO: Breaks backspace in <C-v><S-i> although i binding?
}
{
mode = "i";
key = "<M-BS>";
action = "<C-w>";
options.desc = "Delete Previous Word"; # TODO: Breaks backspace in <C-v><S-i> although i binding?
}
# Clipboard
{
mode = "i";
key = "<C-S-v>";
action = "<Esc>\"+pi";
options.desc = "Paste";
}
{
mode = "i";
key = "<C-v>";
action = "<Esc>\"+pi";
options.desc = "Paste";
}
{
mode = "v";
key = "<C-S-c>";
action = "\"+y";
options.desc = "Copy";
}
{
mode = ["n" "i"];
key = "<C-p>";
action = "<cmd>YankyRingHistory<cr>";
options.desc = "Paste (Yanky)";
}
{
mode = "n";
key = "<C-S-p>";
action = "<cmd>YankyClearHistory<cr>";
options.desc = "Clear Yanky History";
}
# Various
{
mode = "n";
key = "<C-S-h>";
action = "<cmd>nohlsearch<cr>";
options.desc = "Clear Search Highlights";
}
{
mode = "n";
key = "K";
action = "<cmd>lua vim.lsp.buf.hover()<cr>";
options.desc = "LSP Hover";
}
# {
# mode = "n";
# key = "K";
# action = "<cmd>lua require('hover').hover()<cr>";
# options.desc = "LSP Hover";
# }
{
mode = "n";
key = "/";
action = "<cmd>lua Snacks.picker.lines()<cr>";
options.desc = "Find in Buffer";
}
{
mode = ["n" "v"];
key = ";";
action = "%";
options.desc = "Matching ()[]<>";
}
# {
# mode = "v";
# key = ";";
# action = "<Esc>";
# options.desc = "Exit Visual Mode";
# }
];
leader = [
{
mode = "n";
key = "<leader>L";
action = "<cmd>Lazy<cr>";
options.desc = "Lazy Packages";
}
{
mode = "n";
key = "<leader>e";
action = "<cmd>Neotree action=show toggle=true<cr><C-w>=";
options.desc = "Toggle Explorer";
}
{
mode = "n";
key = "<leader>E";
action = "<cmd>Neotree<cr>";
options.desc = "Focus Explorer";
}
{
mode = "n";
key = "<leader>n";
action = "<cmd>Navbuddy<cr>";
options.desc = "Toggle NavBuddy";
}
{
mode = "n";
key = "<leader>p";
action = "<cmd>lua Snacks.picker.pickers()<cr>";
options.desc = "Show Pickers";
}
{
mode = "n";
key = "<leader>N";
action = "<cmd>lua Snacks.picker.notifications()<cr>";
options.desc = "Notifications Picker";
}
{
mode = "n";
key = "<leader>R";
action = "<cmd>lua Snacks.picker.resume()<cr>";
options.desc = "Last Picker";
}
{
mode = "n";
key = "<leader>r";
action = "<cmd>lua vim.g.toggle_rmpc()<cr>"; # Defined in extraConfigLua.lua
options.desc = "Show Rmpc";
}
{
mode = "n";
key = "<leader>i";
action = "<cmd>lua Snacks.picker.icons()<cr>";
options.desc = "Icons Picker";
}
{
mode = "n";
key = "<leader>;";
action = "<cmd>lua Snacks.picker.command_history()<cr>";
options.desc = "Command History";
}
{
mode = "n";
key = "<leader>:";
action = "<cmd>lua Snacks.picker.commands()<cr>";
options.desc = "Commands Picker";
}
{
mode = "n";
key = "<leader>m";
action = "<cmd>lua Snacks.picker.marks()<cr>";
options.desc = "Marks Picker";
}
{
mode = "n";
key = "<leader>j";
action = "<cmd>lua Snacks.picker.jumps()<cr>";
options.desc = "Jumps Picker";
}
{
mode = "n";
key = "<leader>d";
action = "<cmd>lua Snacks.picker.todo_comments()<cr>";
options.desc = "List TODOs";
}
{
mode = "n";
key = "<leader>/";
action = "<cmd>lua Snacks.picker.grep()<cr>";
options.desc = "Find in Project";
}
{
mode = "n";
key = "<leader>Q";
action = "<cmd>lua Snacks.picker.qflist()<cr>";
options.desc = "Quickfix History";
}
# {
# mode = "n";
# key = "<leader>Q";
# action = "<cmd>cexpr []<cr>";
# options.desc = "Clear Quickfix List";
# }
{
mode = "n";
key = "<leader>W";
action = "<cmd>:set wrap!<cr>";
options.desc = "Toggle Word Wrap";
}
{
mode = "n";
key = "<leader>y";
action = "<cmd>Yazi<cr>";
options.desc = "Toggle Yazi";
}
];
leader-file = [
{
mode = "n";
key = "<leader>f";
action = "+file";
}
{
mode = "n";
key = "<leader>ff";
action = "<cmd>lua Snacks.picker.files()<cr>";
options.desc = "Find File";
}
{
mode = "n";
key = "<leader>fl";
action = "<cmd>lua Snacks.picker.recent()<cr>";
options.desc = "Last Files";
}
# {
# mode = "n";
# key = "<leader>fo";
# action = "<cmd>ObsidianSearch<cr>";
# options.desc = "Obsidian Note";
# }
{
mode = "n";
key = "<leader>fr";
action = "<cmd>edit!<cr>";
options.desc = "Reload File";
}
{
mode = "n";
key = "<leader>fu";
action = "<cmd>lua Snacks.picker.und()<cr>";
options.desc = "Undo Picker";
}
{
mode = "n";
key = "<leader>fc";
action = "<cmd>edit ~/.config/nvim/init.lua<cr>";
options.desc = "Open NeoVim Config";
}
{
mode = "n";
key = "<leader>fh";
action = "<cmd>edit ~/.config/hypr/hyprland.conf<cr>";
options.desc = "Open Hyprland Config";
}
{
mode = "n";
key = "<leader>fn";
action = "<cmd>enew<cr>";
options.desc = "New File";
}
{
mode = "n";
key = "<leader>fs";
action.__raw = ''
function()
local filename = vim.fn.input("Enter Filename: ")
vim.cmd("write "..filename)
end
'';
options.desc = "Save File";
}
];
leader-help = [
{
mode = "n";
key = "<leader>h";
action = "+help";
}
# {
# mode = "n";
# key = "<leader>hv";
# action = "<cmd>Telescope vim_options<cr>";
# options.desc = "Telescope Vimopts";
# }
{
mode = "n";
key = "<leader>hk";
action = "<cmd>lua Snacks.picker.keymaps()<cr>";
options.desc = "Keymaps Picker";
}
{
mode = "n";
key = "<leader>hm";
action = "<cmd>lua Snacks.picker.man()<cr>";
options.desc = "Manpages Picker";
}
{
mode = "n";
key = "<leader>hh";
action = "<cmd>lua Snacks.picker.help()<cr>";
options.desc = "Helptags Picker";
}
];
leader-quit = [
{
mode = "n";
key = "<leader>q";
action = "+quit";
}
{
mode = "n";
key = "<leader>qq";
action = "<cmd>quitall<cr>";
options.desc = "Quit";
}
{
mode = "n";
key = "<leader>qQ";
action = "<cmd>quitall!<cr>";
options.desc = "Force Quit";
}
];
leader-session = [
{
mode = "n";
key = "<leader>s";
action = "+session";
}
{
mode = "n";
key = "<leader>sl";
action = "<cmd>lua require('persisted').select()<cr>";
options.desc = "Restore Session";
}
{
mode = "n";
key = "<leader>ss";
action = "<cmd>SessionSave<cr>";
options.desc = "Save Session";
}
{
mode = "n";
key = "<leader>sd";
action = "<cmd>SessionDelete<cr>";
options.desc = "Delete Session";
}
];
leader-buffers = [
{
mode = "n";
key = "<leader>b";
action = "+buffer";
}
{
mode = "n";
key = "<leader>bb";
action = "<cmd>lua Snacks.picker.buffers()<cr>";
options.desc = "Buffers Picker";
}
{
mode = "n";
key = "<leader><Space>";
action = "<cmd>lua Snacks.picker.buffers()<cr>";
options.desc = "Buffers Picker";
}
{
mode = "n";
key = "<leader>bn";
action = "<cmd>bnext<cr>";
options.desc = "Next Buffer";
}
{
mode = "n";
key = "<leader>bp";
action = "<cmd>bprevious<cr>";
options.desc = "Previous Buffer";
}
{
mode = "n";
key = "<leader>bN";
action = "<cmd>enew<cr>";
options.desc = "New Buffer";
}
{
mode = "n";
key = "<leader>bd";
action = "<cmd>lua Snacks.bufdelete()<cr>";
options.desc = "Close Buffer";
}
];
leader-tabs = [
{
mode = "n";
key = "<leader>T";
action = "+tab";
}
# {
# mode = "n";
# key = "<leader>Tt";
# action = "<cmd>Telescope telescope-tabs list_tabs<cr>";
# options.desc = "List Tabpages";
# }
# {
# mode = "n";
# key = "<leader><C-Space>";
# action = "<cmd>Telescope telescope-tabs list_tabs<cr>";
# options.desc = "List Tabpages";
# }
{
mode = "n";
key = "<leader>Tn";
action = "<cmd>tabnext<cr>";
options.desc = "Next Tabpage";
}
{
mode = "n";
key = "<leader>Tp";
action = "<cmd>tabprevious<cr>";
options.desc = "Previous Tabpage";
}
{
mode = "n";
key = "<leader>TN";
action = "<cmd>tabnew<cr>";
options.desc = "New Tabpage";
}
{
mode = "n";
key = "<leader>Td";
action = "<cmd>tabclose<cr>";
options.desc = "Close Tabpage";
}
];
leader-windows = [
{
mode = "n";
key = "<leader>w";
action = "+window";
}
{
mode = "n";
key = "<leader>wd";
action = "<C-w>c";
options.desc = "Close Window";
}
{
mode = "n";
key = "<leader>ws";
action = "<C-w>s";
options.desc = "Split Horizontally";
}
{
mode = "n";
key = "<leader>wv";
action = "<C-w>v";
options.desc = "Split Vertically";
}
{
mode = "n";
key = "<leader>w=";
action = "<C-w>=";
options.desc = "Balance Windows";
}
{
mode = "n";
key = "<leader>wh";
action = "<C-w>h";
options.desc = "Goto Left Window";
}
{
mode = "n";
key = "<leader>wl";
action = "<C-w>l";
options.desc = "Goto Wight Window";
}
{
mode = "n";
key = "<leader>wj";
action = "<C-w>j";
options.desc = "Goto Bottom Window";
}
{
mode = "n";
key = "<leader>wk";
action = "<C-w>k";
options.desc = "Goto Top Window";
}
{
mode = "n";
key = "<leader>ww";
action = "<cmd>lua vim.api.nvim_set_current_win(require('window-picker').pick_window() or vim.api.nvim_get_current_win())<cr>";
options.desc = "Jump to Window";
}
{
mode = "n";
key = "<leader>wm";
action = "<cmd>WinShift<cr>";
options.desc = "Move Window";
}
];
leader-git = [
{
mode = "n";
key = "<leader>g";
action = "+git";
}
{
mode = "n";
key = "<leader>gg";
action = "<cmd>lua Snacks.lazygit.open()<cr>";
options.desc = "LazyGit";
}
{
mode = "n";
key = "<leader>gm";
action = "<cmd>lua Snacks.git.blame_line()<cr>";
options.desc = "Git Blame";
}
{
mode = "n";
key = "<leader>gs";
action = "<cmd>lua Snacks.picker.git_status()<cr>";
options.desc = "Git Status";
}
{
mode = "n";
key = "<leader>gl";
action = "<cmd>lua Snacks.picker.git_log()<cr>";
options.desc = "Git Log";
}
{
mode = "n";
key = "<leader>gb";
action = "<cmd>lua Snacks.picker.git_branches()<cr>";
options.desc = "Git Branches";
}
{
mode = "n";
key = "<leader>gf";
action = "<cmd>lua Snacks.picker.git_log_file()<cr>";
options.desc = "Git File History";
}
{
mode = "n";
key = "<leader>gd";
action = "<cmd>DiffviewOpen<cr>";
options.desc = "Git DiffView";
}
];
leader-code = [
{
mode = "n";
key = "<leader>c";
action = "+code";
}
{
mode = "n";
key = "<leader>cf";
action = "<cmd>lua require('conform').format()<cr>";
options.desc = "Format Buffer";
}
{
mode = "n";
key = "<leader>cd";
action = "<cmd>lua vim.diagnostic.open_float()<cr>";
options.desc = "Line Diagnostics";
}
{
mode = "n";
key = "<leader>cD";
action = "<cmd>lua Snacks.picker.diagnostics()<cr>";
options.desc = "List Diagnostics";
}
{
mode = "n";
key = "<leader>cr";
action = "<cmd>lua vim.lsp.buf.rename()<cr>";
options.desc = "Rename Symbol";
}
{
mode = "n";
key = "<leader>ca";
action = "<cmd>lua vim.lsp.buf.code_action()<cr>";
options.desc = "Code Actions";
}
# {
# mode = "n";
# key = "<leader>cI";
# action = "<cmd>Telescope lsp_incoming_calls<cr>";
# options.desc = "LSP Incoming Calls";
# }
# {
# mode = "n";
# key = "<leader>cO";
# action = "<cmd>Telescope lsp_outgoing_calls<cr>";
# options.desc = "LSP Outgoing Calls";
# }
{
mode = "n";
key = "<leader>cc";
action = "<cmd>Neogen<cr>";
options.desc = "Generate Doc Comment";
}
# Toggles
{
mode = "n";
key = "<leader>t";
action = "+toggle";
}
{
mode = "n";
key = "<leader>td";
action = "<cmd>ToggleInlineDiagnostics<cr>";
options.desc = "Inline Diagnostics";
}
{
mode = "n";
key = "<leader>tt";
action = "<cmd>Trouble diagnostics toggle focus=false win.position=left<cr>";
options.desc = "Trouble Diagnostics";
}
{
mode = "n";
key = "<leader>tD";
action = "<cmd>Trouble todo toggle focus=false win.position=left<cr>";
options.desc = "Toggle TODOs";
}
{
mode = "n";
key = "<leader>ts";
action = "<cmd>Trouble symbols toggle focus=false win.position=left<cr>";
options.desc = "Trouble Symbols";
}
{
mode = "n";
key = "<leader>tf";
action = "<cmd>ToggleAutoformat<cr>";
options.desc = "Format on Save";
}
{
mode = "n";
key = "<leader>tl";
action = "<cmd>ToggleAutoLint<cr>";
options.desc = "Lint on Save";
}
# GoTo
{
mode = "n";
key = "<leader>cg";
action = "+goto";
}
{
mode = "n";
key = "<leader>cgh";
action = "<cmd>ClangdSwitchSourceHeader<cr>";
options.desc = "Switch C/C++ Source/Header";
}
{
mode = "n";
key = "<leader>cgr";
action = "<cmd>lua Snacks.picker.lsp_references()<cr>";
options.desc = "LSP References";
}
{
mode = "n";
key = "<leader>cgd";
action = "<cmd>lua Snacks.picker.lsp_definitions()<cr>";
options.desc = "LSP Definitions";
}
{
mode = "n";
key = "<leader>cgi";
action = "<cmd>lua Snacks.picker.lsp_implementations()<cr>";
options.desc = "LSP Implementations";
}
{
mode = "n";
key = "<leader>cgt";
action = "<cmd>lua Snacks.picker.lsp_type_definitions()<cr>";
options.desc = "LSP Type Definitions";
}
{
mode = "n";
key = "<leader>cge";
action = "<cmd>lua vim.diagnostic.goto_next()<cr>";
options.desc = "Next Diagnostic";
}
{
mode = "n";
key = "<C-e>";
action = "<cmd>lua vim.diagnostic.goto_next()<cr>";
options.desc = "Next Diagnostic";
}
{
mode = "n";
key = "<leader>cgE";
action = "<cmd>lua vim.diagnostic.goto_prev()<cr>";
options.desc = "Previous Diagnostic";
}
{
mode = "n";
key = "<C-S-e>";
action = "<cmd>lua vim.diagnostic.goto_prev()<cr>";
options.desc = "Previous Diagnostic";
}
{
mode = "n";
key = "<C-q>";
action = "<cmd>cnext<cr>";
options.desc = "Next Quickfix Item";
}
{
mode = "n";
key = "<leader>cgq";
action = "<cmd>cnext<cr>";
options.desc = "Next Quickfix Item";
}
{
mode = "n";
key = "<C-S-q>";
action = "<cmd>cprevious<cr>";
options.desc = "Previous Quickfix Item";
}
{
mode = "n";
key = "<leader>cgQ";
action = "<cmd>cprevious<cr>";
options.desc = "Previous Quickfix Item";
}
];
localleader-latex = [
];
in
builtins.concatLists [
disabled-mappings
no-leader
leader
leader-file
leader-help
leader-quit
leader-session
leader-buffers
leader-tabs
leader-windows
leader-git
leader-code
localleader-latex
]

View File

@ -0,0 +1,58 @@
{...}: [
{
mode = "n";
key = "<localleader>t";
action = "<cmd>VimtexTocToggle<cr>";
options.desc = "Vimtex ToC";
options.buffer = true;
}
{
mode = "n";
key = "<localleader>c";
action = "<cmd>VimtexCompile<cr>";
options.desc = "Vimtex Compile";
options.buffer = true;
}
{
mode = "n";
key = "<localleader>C";
action = "<cmd>VimtexClean!<cr>";
options.desc = "Vimtex Clean";
options.buffer = true;
}
{
mode = "n";
key = "<localleader>v";
action = "<cmd>VimtexView<cr>";
options.desc = "Vimtex View";
options.buffer = true;
}
{
mode = "n";
key = "<localleader>I";
action = "<cmd>VimtexInfo<cr>";
options.desc = "Vimtex Info";
options.buffer = true;
}
{
mode = "n";
key = "<localleader>,";
action = "<cmd>VimtexContextMenu<cr>";
options.desc = "Vimtex Context Menu";
options.buffer = true;
}
{
mode = "n";
key = "<localleader>e";
action = "<cmd>VimtexErrors<cr>";
options.desc = "Vimtex Errors";
options.buffer = true;
}
{
mode = "n";
key = "<localleader>p";
action = "<cmd>VimtexDocPackage<cr>";
options.desc = "Vimtex Package Docs";
options.buffer = true;
}
]

View File

@ -0,0 +1,16 @@
{...}: [
{
mode = "n";
key = "<localleader>t";
action = "<cmd>Markview toggle<cr>";
options.desc = "Toggle Conceal";
options.buffer = true;
}
{
mode = "n";
key = "<localleader>s";
action = "<cmd>Markview splitToggle<cr>";
options.desc = "Toggle Split";
options.buffer = true;
}
]

View File

@ -0,0 +1,7 @@
fork = true # Start neovide detached
frame = "none" # full, buttonless, none
idle = true # Don't render frames without changes
title-hidden = true
tabs = false
# maximized = true
# vsync = true

View File

@ -0,0 +1,11 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "NeoVim";
alias = mkBoolOption false "Link nvim to vim/vi";
neovide = mkEnableOption "NeoVide";
}

View File

@ -0,0 +1,33 @@
return {
-- The first list contains manually expanded snippts
--
-- The fmta function accepts a string ([[]] denote multiline strings) and node table.
-- The node table entry order corresponds to the delimiters,
-- the indices denote the jumping order, 0 is jumped to last.
--
-- Example:
-- s("beg", fmta([[
-- \begin{<>}
-- <>
-- \end{<>}]],
-- { i(1), i(0), rep(1) }
-- )),
--
-- The first jumping position (1) fills the \begin{<>} (and \end{<>} because of the repeat).
-- The last jumping position (0) fills the body.
-- \begin{environment}
s(
"beg",
fmta(
[[
\begin{<>}
<>
\end{<>}
]],
{ i(1), i(0), rep(1) }
)
),
}, {
-- The second list contains autosnippets
}

View File

@ -0,0 +1,11 @@
# Core settings appear at the top
# (the "global" section).
[formats]
# Format associations appear under
# the optional "formats" section.
[*]
# Format-specific settings appear
# under a user-provided "glob"
# pattern.

View File

@ -0,0 +1,66 @@
_: {
showmode = false; # Status line already shows this
backspace = ["indent" "eol" "start"];
termguicolors = true; # Required by multiple plugins
hidden = true; # Don't unload buffers immediately (required for terminal persistence)
mouse = "a";
completeopt = ["menuone" "noselect" "noinsert"];
timeoutlen = 50; # Controls which-key delay
pumheight = 0;
formatexpr = "v:lua.require('conform').formatexpr()";
laststatus = 3; # Global statusline
winblend = 30; # Floating popup transparency
winborder = "rounded";
sessionoptions = ["buffers" "curdir" "folds" "globals" "help" "skiprtp" "tabpages" "winsize"]; # What should be saved when creating a session
showtabline = 2; # Disable tabline with 0, show for > 1 with 1, always show with 2
conceallevel = 2;
# Cursor
ruler = true; # Show cursor position in status line
number = true;
relativenumber = true;
signcolumn = "yes"; # Always show to reduce window jumping
cursorline = true;
scrolloff = 10;
# Folding
foldcolumn = "0";
foldlevel = 99;
foldlevelstart = 99;
foldenable = true;
# foldmethod = "expr";
# foldexpr = "nvim_treesitter#foldexpr()";
# Files
encoding = "utf-8";
fileencoding = "utf-8";
# swapfile = true;
# backup = false;
undofile = true;
undodir = "/home/christoph/.vim/undo";
undolevels = 10000;
# autochdir = true;
confirm = true;
# Search
incsearch = true; # Already highlight results while typing
hlsearch = true;
ignorecase = true;
smartcase = true;
grepprg = "rg --vimgrep";
grepformat = "%f:%l:%c:%m";
# Indentation
autoindent = true; # Use previous line indentation level - Might mess up comment indentation
smartindent = true; # Like autoindent but recognizes some C syntax - Might mess up comment indentation
cindent = false;
# cinkeys = "0{,0},0),0],:,!^F,o,O,e"; # Fix comment (#) indentation and intellitab (somehow)
smarttab = true;
expandtab = true;
shiftwidth = 4;
tabstop = 4;
softtabstop = 4;
splitbelow = true;
splitright = true;
}

View File

@ -0,0 +1,488 @@
{
config,
color,
}: {
enable = true;
systemd = {
enable = false;
restartIfChanged = true;
};
# Deprecated
# enableClipboard = true;
# enableBrightnessControl = false;
# enableColorPicker = true;
# enableSystemSound = false;
enableSystemMonitoring = true;
enableVPN = true;
enableDynamicTheming = false;
enableAudioWavelength = true;
enableCalendarEvents = false;
niri = {
enableKeybinds = false;
enableSpawn = false;
};
# This is generated from the DMS settings dialog.
# Run: nix eval --impure --expr 'builtins.fromJSON (builtins.readFile ~/.config/DankMaterialShell/settings.json)'
settings = {
# Bar
barConfigs = [
{
# Widgets
leftWidgets = [
{
enabled = true;
id = "launcherButton";
}
{
enabled = true;
id = "workspaceSwitcher";
}
{
enabled = true;
focusedWindowCompactMode = true;
id = "focusedWindow";
}
];
centerWidgets = [
{
enabled = true;
id = "music";
mediaSize = 1;
}
];
rightWidgets = [
{
enabled = true;
id = "cpuUsage";
minimumWidth = true;
}
{
enabled = true;
id = "memUsage";
minimumWidth = true;
}
{
enabled = true;
id = "diskUsage";
}
{
enabled = true;
id = "clipboard";
}
{
enabled = true;
id = "controlCenterButton";
}
{
enabled = true;
id = "systemTray";
}
{
clockCompactMode = true;
enabled = true;
id = "clock";
}
{
enabled = true;
id = "notificationButton";
}
];
enabled = true;
id = "default";
name = "Main Bar";
# Behavior
autoHide = false;
autoHideDelay = 250;
maximizeDetection = true;
openOnOverview = false;
# Border
borderColor = "surfaceText";
borderEnabled = false;
borderOpacity = 1;
borderThickness = 2;
gothCornerRadiusOverride = false;
gothCornerRadiusValue = 12;
gothCornersEnabled = false;
# Styling
position = 0;
fontScale = 1.1;
bottomGap = 0;
innerPadding = 4;
noBackground = false;
popupGapsAuto = true;
popupGapsManual = 4;
spacing = 0;
transparency = 1;
widgetOutlineColor = "primary";
widgetOutlineEnabled = false;
widgetOutlineOpacity = 1;
widgetOutlineThickness = 2;
widgetTransparency = 1;
squareCorners = true;
screenPreferences = ["all"];
showOnLastDisplay = true;
visible = true;
}
];
# Power saving
acLockTimeout = 0;
acMonitorTimeout = 0;
acProfileName = "";
acSuspendBehavior = 0;
acSuspendTimeout = 0;
animationSpeed = 1;
# Launcher
appLauncherGridColumns = 4;
appLauncherViewMode = "list";
launchPrefix = "";
launcherLogoBrightness = 0.5;
launcherLogoColorInvertOnMode = false;
launcherLogoColorOverride = "";
launcherLogoContrast = 1;
launcherLogoCustomPath = "";
launcherLogoMode = "os";
launcherLogoSizeOffset = 0;
# Audio
audioInputDevicePins = {};
audioOutputDevicePins = {};
audioVisualizerEnabled = true;
# Battery
batteryLockTimeout = 0;
batteryMonitorTimeout = 0;
batteryProfileName = "";
batterySuspendBehavior = 0;
batterySuspendTimeout = 0;
# Wallpaper
blurWallpaperOnOverview = true;
blurredWallpaperLayer = false;
wallpaperFillMode = "Fill";
# Control center
controlCenterShowAudioIcon = true;
controlCenterShowBatteryIcon = false;
controlCenterShowBluetoothIcon = true;
controlCenterShowBrightnessIcon = false;
controlCenterShowMicIcon = true;
controlCenterShowNetworkIcon = true;
controlCenterShowPrinterIcon = false;
controlCenterShowVpnIcon = true;
controlCenterWidgets = [
{
enabled = true;
id = "volumeSlider";
width = 50;
}
{
enabled = true;
id = "brightnessSlider";
width = 50;
}
{
enabled = true;
id = "wifi";
width = 50;
}
{
enabled = true;
id = "bluetooth";
width = 50;
}
{
enabled = true;
id = "audioOutput";
width = 50;
}
{
enabled = true;
id = "audioInput";
width = 50;
}
{
enabled = true;
id = "nightMode";
width = 50;
}
{
enabled = true;
id = "darkMode";
width = 50;
}
];
# Theme
currentThemeName = "custom";
currentThemeCategory = "registry";
customThemeFile = "${config.paths.dotfiles}/dankmaterialshell/catppuccin-mauve.json";
# Styling
cornerRadius = 10;
customAnimationDuration = 500;
fontFamily = "MonoLisa Normal";
monoFontFamily = "MonoLisa Normal";
fontScale = 1;
fontWeight = 500;
gtkThemingEnabled = false;
iconTheme = "System Default";
# Lock
fadeToLockEnabled = true;
fadeToLockGracePeriod = 5;
lockBeforeSuspend = false;
lockDateFormat = "yyyy-MM-dd";
lockScreenActiveMonitor = "all";
lockScreenInactiveColor = "#000000";
lockScreenShowDate = true;
lockScreenShowPasswordField = true;
lockScreenShowPowerActions = true;
lockScreenShowProfileImage = true;
lockScreenShowSystemIcons = true;
lockScreenShowTime = true;
loginctlLockIntegration = true;
# Notifications
notificationOverlayEnabled = false;
notificationPopupPosition = 0;
notificationTimeoutCritical = 0;
notificationTimeoutLow = 5000;
notificationTimeoutNormal = 5000;
# OSD
osdAlwaysShowValue = true;
osdAudioOutputEnabled = true;
osdBrightnessEnabled = true;
osdCapsLockEnabled = true;
osdIdleInhibitorEnabled = true;
osdMediaVolumeEnabled = true;
osdMicMuteEnabled = true;
osdPosition = 7;
osdPowerProfileEnabled = false;
osdVolumeEnabled = true;
# Power menu
powerActionConfirm = true;
powerActionHoldDuration = 0.5;
powerMenuActions = ["reboot" "logout" "poweroff" "lock" "restart"];
powerMenuDefaultAction = "poweroff";
powerMenuGridLayout = false;
# Settings
focusedWindowCompactMode = false;
hideBrightnessSlider = false;
keyboardLayoutNameCompactMode = false;
modalDarkenBackground = true;
nightModeEnabled = false;
niriOverviewOverlayEnabled = true;
showBattery = false;
showCapsLockIndicator = false;
showClipboard = true;
showClock = true;
showControlCenterButton = true;
showCpuTemp = true;
showCpuUsage = true;
showDock = false;
showFocusedWindow = true;
showGpuTemp = false;
showLauncherButton = true;
showMemUsage = true;
showMusic = true;
showNotificationButton = true;
showOccupiedWorkspacesOnly = false;
showPrivacyButton = false;
showSystemTray = true;
showWorkspaceApps = false;
showWorkspaceIndex = false;
showWorkspacePadding = false;
showWorkspaceSwitcher = true;
soundNewNotification = true;
soundPluggedIn = true;
soundVolumeChanged = true;
soundsEnabled = false;
# Launcher
sortAppsAlphabetically = false;
spotlightCloseNiriOverview = true;
spotlightModalViewMode = "list";
# Clock
use24HourClock = true;
showSeconds = true;
clockCompactMode = false;
clockDateFormat = "yyyy-MM-dd";
# Media
waveProgressEnabled = true;
scrollTitleEnabled = true;
# Weather
showWeather = true;
useFahrenheit = false;
useAutoLocation = false;
weatherCoordinates = "51.5142273,7.4652789";
weatherEnabled = true;
weatherLocation = "Dortmund, Nordrhein-Westfalen";
# Workspaces
workspaceNameIcons = {};
workspaceScrolling = false;
workspacesPerMonitor = true;
# Dock
dockAutoHide = false;
dockBorderColor = "surfaceText";
dockBorderEnabled = false;
dockBorderOpacity = 1;
dockBorderThickness = 1;
dockBottomGap = 0;
dockGroupByApp = false;
dockIconSize = 40;
dockIndicatorStyle = "circle";
dockMargin = 0;
dockOpenOnOverview = false;
dockPosition = 1;
dockSpacing = 4;
dockTransparency = 1;
# Random shit
widgetBackgroundColor = "sc";
widgetColorMode = "default";
wifiNetworkPins = {};
brightnessDevicePins = {};
bluetoothDevicePins = {};
centeringMode = "index";
useSystemSoundTheme = false;
vpnLastConnected = "";
syncModeWithPortal = true;
terminalsAlwaysDark = false;
updaterCustomCommand = "";
updaterTerminalAdditionalParams = "";
updaterUseCustomCommand = false;
showOnLastDisplay = {};
dwlShowAllTags = false;
enableFprint = false;
enabledGpuPciIds = [];
customPowerActionHibernate = "";
customPowerActionLock = "";
customPowerActionLogout = "";
customPowerActionPowerOff = "";
customPowerActionReboot = "";
customPowerActionSuspend = "";
displayNameMode = "system";
matugenScheme = "scheme-tonal-spot";
matugenTargetMonitor = "";
matugenTemplateAlacritty = true;
matugenTemplateDgop = true;
matugenTemplateFirefox = true;
matugenTemplateFoot = true;
matugenTemplateGhostty = true;
matugenTemplateGtk = true;
matugenTemplateKcolorscheme = true;
matugenTemplateKitty = true;
matugenTemplateNiri = true;
matugenTemplatePywalfox = true;
matugenTemplateQt5ct = true;
matugenTemplateQt6ct = true;
matugenTemplateVesktop = true;
matugenTemplateVscode = true;
matugenTemplateWezterm = true;
notepadFontFamily = "";
notepadFontSize = 14;
notepadLastCustomTransparency = 0.7;
notepadShowLineNumbers = false;
notepadTransparencyOverride = -1;
notepadUseMonospace = true;
maxFprintTries = 15;
maxWorkspaceIcons = 3;
mediaSize = 1;
networkPreference = "auto";
selectedGpuIndex = 0;
popupTransparency = 1;
privacyShowCameraIcon = false;
privacyShowMicIcon = false;
privacyShowScreenShareIcon = false;
qtThemingEnabled = false;
runDmsMatugenTemplates = false;
runUserMatugenTemplates = false;
runningAppsCompactMode = true;
runningAppsCurrentWorkspace = false;
runningAppsGroupByApp = false;
screenPreferences = {};
configVersion = 2;
};
session = {
# Settings
doNotDisturb = false;
isLightMode = false;
weatherHourlyDetailed = true;
# Night
nightModeAutoEnabled = true;
nightModeAutoMode = "time";
nightModeEnabled = true;
nightModeEndHour = 6;
nightModeEndMinute = 0;
nightModeHighTemperature = 6500;
nightModeLocationProvider = "";
nightModeStartHour = 22;
nightModeStartMinute = 0;
nightModeTemperature = 5500;
nightModeUseIPLocation = false;
# Hardware
nonNvidiaGpuTempEnabled = false;
nvidiaGpuTempEnabled = false;
selectedGpuIndex = 0;
wifiDeviceOverride = "";
enabledGpuPciIds = [];
lastBrightnessDevice = "";
# Wallpapers
perModeWallpaper = false;
perMonitorWallpaper = false;
wallpaperCyclingEnabled = false;
wallpaperCyclingInterval = 300;
wallpaperCyclingMode = "interval";
wallpaperCyclingTime = "06:00";
wallpaperPath = "/home/christoph/NixFlake/wallpapers/Windows.jpg";
wallpaperPathDark = "";
wallpaperPathLight = "";
wallpaperTransition = "iris bloom";
# Random shit
includedTransitions = ["fade" "wipe" "disc" "stripes" "iris bloom" "pixelate" "portal"];
launchPrefix = "";
latitude = 0;
longitude = 0;
pinnedApps = [];
hiddenTrayIds = [];
recentColors = [];
showThirdPartyPlugins = true;
# Ultra random shit
monitorCyclingSettings = {};
monitorWallpapers = {};
monitorWallpapersDark = {};
monitorWallpapersLight = {};
brightnessExponentValues = {};
brightnessExponentialDevices = {};
brightnessUserSetValues = {};
configVersion = 1;
};
}

View File

@ -0,0 +1,588 @@
{
config,
nixosConfig,
lib,
mylib,
inputs,
pkgs,
...
}: let
inherit (config.modules) niri color;
in {
options.modules.niri = import ./options.nix {inherit lib mylib;};
config = lib.mkIf niri.enable rec {
assertions = [
{
assertion = nixosConfig.programs.niri.enable;
message = "Can't enable Niri config with Niri disabled!";
}
{
assertion = !(programs.noctalia-shell.enable && programs.dank-material-shell.enable);
message = "Can't enable Noctalia and DankMaterialShell at the same time!";
}
];
gtk = {
enable = true;
iconTheme.package = color.iconPackage;
iconTheme.name = color.iconTheme;
};
# Disable niri polkit if we use DMS, as it has its own
systemd.user.services.niri-flake-polkit = lib.mkForce {};
home = {
sessionVariables = {
QT_QPA_PLATFORMTHEME = "gtk3"; # For Noctalia
GDK_BACKEND = "wayland"; # For screen sharing
};
pointerCursor = {
gtk.enable = true;
x11.enable = true;
package = color.cursorPackage;
name = color.cursor;
size = color.cursorSize;
};
packages = with pkgs; [
xwayland-satellite
ncpamixer # Audio control
nautilus # Fallback file chooser used by xdg-desktop-portal-gnome
# In case we fallback to the default config
alacritty
fuzzel
];
};
programs = {
# TODO: Those should be modules with their own options
noctalia-shell = import ./noctalia.nix {inherit color;};
dank-material-shell = import ./dankMaterialShell.nix {inherit config color;};
# TODO: Extract options
niri = {
# enable = true; # Enabled in system module
settings = {
input = {
focus-follows-mouse = {
enable = true;
max-scroll-amount = "0%"; # Skip partial windows that would scroll the viewport on focus
};
keyboard = {
xkb = {
layout = "us";
variant = "altgr-intl";
options = "nodeadkeys";
};
};
touchpad = {
click-method = "clickfinger";
tap = true;
drag = true;
dwt = true;
natural-scroll = true;
scroll-method = "two-finger";
};
};
hotkey-overlay = {
hide-not-bound = true;
skip-at-startup = true;
};
prefer-no-csd = true; # Disable client-side decorations (e.g. window titlebars)
spawn-at-startup = [
# TODO: Depend on options
# {argv = ["noctalia-shell"];}
{argv = ["dms" "run"];}
{argv = ["kitty" "--hold" "fastfetch"];}
{argv = ["zeal"];}
{argv = ["protonvpn-app"];}
{argv = ["fcitx5"];}
{argv = ["jellyfin-mpv-shim"];}
{sh = "sleep 5s && nextcloud --background";}
{sh = "sleep 5s && keepassxc";}
];
workspaces = {
"1" = {open-on-output = "DP-1";};
"2" = {open-on-output = "DP-1";};
"3" = {open-on-output = "DP-1";};
"4" = {open-on-output = "DP-1";};
"5" = {open-on-output = "DP-1";};
"6" = {open-on-output = "DP-1";};
"7" = {open-on-output = "DP-1";};
"8" = {open-on-output = "DP-1";};
"9" = {open-on-output = "DP-1";};
"10" = {open-on-output = "DP-2";};
};
outputs = {
"DP-1" = {
focus-at-startup = true;
mode = {
width = 3440;
height = 1440;
refresh = 164.999;
};
position = {
x = 1920;
y = 0;
};
};
"DP-2" = {
focus-at-startup = false;
mode = {
width = 1920;
height = 1080;
refresh = 60.0;
};
position = {
x = 0;
y = 0;
};
};
};
cursor = {
hide-when-typing = true;
theme = color.cursor;
size = color.cursorSize;
};
layout = {
# This border is drawn INSIDE the window
border = {
enable = true;
width = 2;
active = {color = color.hex.accent;};
inactive = {color = color.hex.base;};
};
# This border is drawn OUTSIDE of the focused window
focus-ring = {
enable = false;
};
# Hint where a dragged window will be inserted
insert-hint = {
enable = true;
display = {color = color.hex.accentDim;};
};
always-center-single-column = true;
# Gaps between windows
gaps = 8;
# Gaps at screen borders
struts = {
# left = 8;
# right = 8;
top = 4; # Somehow the bar eclusivity doesn't work as expected
bottom = 2;
};
};
gestures = {
hot-corners = {enable = false;};
};
window-rules = [
# Rules for all windows
{
default-column-width.proportion = 0.5;
default-window-height.proportion = 1.0;
# Rounded corners
clip-to-geometry = true;
geometry-corner-radius = {
bottom-left = 8.0;
bottom-right = 8.0;
top-left = 8.0;
top-right = 8.0;
};
# open-floating = false;
# open-focused = false;
# open-fullscreen = false;
# open-maximized = false;
# open-on-output = "DP-1";
# open-on-workspace = "2";
# opacity = 0.8;
}
# Rules for specific windows
{
matches = [{app-id = "Zotero";}];
open-on-workspace = "2";
}
{
matches = [{app-id = "neovide";}];
open-on-workspace = "2";
open-maximized = true;
}
{
matches = [{app-id = "code-url-handler";}];
open-on-workspace = "2";
open-floating = true;
}
{
matches = [{app-id = "obsidian";}];
open-on-workspace = "3";
}
{
matches = [{app-id = "firefox";}];
open-on-workspace = "4";
open-maximized = true;
}
{
matches = [{app-id = "Google-chrome";}];
open-on-workspace = "4";
}
{
matches = [{app-id = "chromium-browser";}];
open-on-workspace = "4";
}
{
matches = [{app-id = "org.qutebrowser.qutebrowser";}];
open-on-workspace = "4";
}
{
matches = [{app-id = "steam";}];
open-on-workspace = "5";
}
{
matches = [{app-id = "steam_app_(.+)";}];
open-on-workspace = "6";
open-floating = true;
open-maximized = true;
}
{
matches = [{app-id = "signal";}];
open-on-workspace = "7";
open-maximized = true;
}
{
matches = [{app-id = "discord";}];
open-on-workspace = "9";
open-maximized = true;
}
];
layer-rules = [
{
# Set the overview wallpaper on the backdrop.
matches = [{namespace = "^noctalia-overview*";}];
place-within-backdrop = true;
}
];
debug = {
# Allows notification actions and window activation from Noctalia.
honor-xdg-activation-with-invalid-serial = [];
};
# TODO: Only start hypr... stuff with hyprland, not systemd (hypridle, hyprpaper currently)
# TODO: Move values to config option and set in home/christoph/niri.nix
binds = with config.lib.niri.actions; {
# Applications
"Mod+T" = {
action = spawn "kitty";
hotkey-overlay = {title = "Spawn Kitty.";};
};
"Mod+E" = {
action = spawn "kitty" "--title=Yazi" "yazi";
hotkey-overlay = {title = "Spawn Yazi.";};
};
"Mod+B" = {
action = spawn "kitty" "--title=Btop" "btop";
hotkey-overlay = {title = "Spawn Btop.";};
};
"Mod+R" = {
action = spawn "kitty" "--title=Rmpc" "rmpc";
hotkey-overlay = {title = "Spawn Rmpc.";};
};
"Mod+N" = {
action = spawn "neovide";
hotkey-overlay = {title = "Spawn Neovide.";};
};
"Mod+Ctrl+N" = {
action = spawn "kitty" "--title=Navi" "navi";
hotkey-overlay = {title = "Call Navi for help.";};
};
"Mod+Shift+N" = {
action = spawn "neovide" "${config.paths.dotfiles}/navi/christoph.cheat";
hotkey-overlay = {title = "Edit the Navi cheats.";};
};
"Mod+Shift+F" = {
action = spawn "neovide" "${config.paths.dotfiles}/flake.nix";
hotkey-overlay = {title = "Edit the NixFlake.";};
};
# TODO: Enable with Noctalia option
# Noctalia
# "Mod+A" = {
# action = spawn "noctalia-shell" "ipc" "call" "launcher" "toggle";
# hotkey-overlay = {title = "Toggle the application launcher.";};
# };
# "Mod+Ctrl+L" = {
# action = spawn "noctalia-shell" "ipc" "call" "lockScreen" "lock";
# hotkey-overlay = {title = "Lock the screen.";};
# };
# "Mod+W" = {
# action = spawn "noctalia-shell" "ipc" "call" "wallpaper" "toggle";
# hotkey-overlay = {title = "Toggle the wallpaper chooser.";};
# };
# "Mod+Escape" = {
# action = spawn "noctalia-shell" "ipc" "call" "sessionMenu" "toggle";
# hotkey-overlay = {title = "Toggle the session menu.";};
# };
# TODO: Enable with DMS option
# DankMaterialShell
"Mod+A" = {
action = spawn "dms" "ipc" "call" "spotlight" "toggle";
hotkey-overlay = {title = "Toggle the application launcher.";};
};
"Mod+Ctrl+L" = {
action = spawn "dms" "ipc" "call" "lock" "lock";
hotkey-overlay = {title = "Lock the screen.";};
};
"Mod+Escape" = {
action = spawn "dms" "ipc" "call" "powermenu" "toggle";
hotkey-overlay = {title = "Toggle the session menu.";};
};
"Mod+C" = {
action = spawn "dms" "ipc" "call" "clipboard" "toggle";
hotkey-overlay = {title = "Show clipboard history.";};
};
# Screenshots
"Mod+S" = {
action.screenshot-window = {write-to-disk = true;};
hotkey-overlay = {title = "Take a screenshot of the current window.";};
};
"Mod+Shift+S" = {
action.screenshot = {show-pointer = true;};
hotkey-overlay = {title = "Take a screenshot of a region.";};
};
# Niri
"Mod+Shift+Slash" = {
action = show-hotkey-overlay;
hotkey-overlay = {hidden = true;};
};
# "Alt+Tab" = {
# action = "next-window";
# hotkey-overlay = {title = "Switch to next window.";};
# };
# "Alt+Shift+Tab" = {
# action = "previous-window";
# hotkey-overlay = {title = "Switch to previous window.";};
# };
# Audio
"XF86AudioRaiseVolume" = {
action = spawn "wpctl" "set-volume" "-l" "1.5" "@DEFAULT_AUDIO_SINK@" "5%+";
hotkey-overlay = {hidden = true;};
};
"XF86AudioLowerVolume" = {
action = spawn "wpctl" "set-volume" "-l" "1.5" "@DEFAULT_AUDIO_SINK@" "5%-";
hotkey-overlay = {hidden = true;};
};
"XF86AudioPlay" = {
action = spawn "playerctl" "play-pause";
hotkey-overlay = {hidden = true;};
};
"XF86AudioPrev" = {
action = spawn "playerctl" "previous";
hotkey-overlay = {hidden = true;};
};
"XF86AudioNext" = {
action = spawn "playerctl" "next";
hotkey-overlay = {hidden = true;};
};
# Niri windows
"Mod+Q" = {
action = close-window;
hotkey-overlay = {title = "Close the current window.";};
};
"Mod+F" = {
action = fullscreen-window;
hotkey-overlay = {title = "Toggle between fullscreen and tiled window.";};
};
"Mod+Equal" = {
action = set-column-width "+10%";
hotkey-overlay = {title = "Increase column width";};
};
"Mod+Minus" = {
action = set-column-width "-10%";
hotkey-overlay = {title = "Decrease column width";};
};
"Mod+Shift+M" = {
action = set-column-width "50%";
hotkey-overlay = {title = "Set column width to 50%";};
};
"Mod+M" = {
action = maximize-column;
hotkey-overlay = {title = "Maximize column.";};
};
"Mod+V" = {
action = toggle-window-floating;
hotkey-overlay = {title = "Toggle between floating and tiled window.";};
};
"Mod+O" = {
action = toggle-overview;
hotkey-overlay = {title = "Toggle overlay.";};
};
"Mod+H" = {
action = focus-column-or-monitor-left;
hotkey-overlay = {title = "Focus column on the left. Equivalent bindings for other directions.";};
};
"Mod+J" = {
action = focus-window-or-workspace-down;
hotkey-overlay = {hidden = true;};
};
"Mod+K" = {
action = focus-window-or-workspace-up;
hotkey-overlay = {hidden = true;};
};
"Mod+L" = {
action = focus-column-or-monitor-right;
hotkey-overlay = {hidden = true;};
};
"Mod+WheelScrollUp" = {
action = focus-column-left;
hotkey-overlay = {title = "Focus column on the left. Equivalent binding for other direction.";};
};
"Mod+WheelScrollDown" = {
action = focus-column-right;
hotkey-overlay = {hidden = true;};
};
"Mod+Shift+WheelScrollUp" = {
action = focus-workspace-up;
hotkey-overlay = {title = "Focus previous workspace. Equivalent binding for other direction.";};
};
"Mod+Shift+WheelScrollDown" = {
action = focus-workspace-down;
hotkey-overlay = {hidden = true;};
};
"Mod+Shift+H" = {
action = move-column-left-or-to-monitor-left;
hotkey-overlay = {title = "Move column to the left. Equivalent bindings for other directions.";};
};
"Mod+Shift+J" = {
action = move-window-down-or-to-workspace-down;
hotkey-overlay = {hidden = true;};
};
"Mod+Shift+K" = {
action = move-window-up-or-to-workspace-up;
hotkey-overlay = {hidden = true;};
};
"Mod+Shift+L" = {
action = move-column-right-or-to-monitor-right;
hotkey-overlay = {hidden = true;};
};
# Niri workspaces
"Mod+1" = {
action = focus-workspace 1;
hotkey-overlay = {title = "Focus workspace 1. Equivalent bindings for other workspaces.";};
};
"Mod+2" = {
action = focus-workspace 2;
hotkey-overlay = {hidden = true;};
};
"Mod+3" = {
action = focus-workspace 3;
hotkey-overlay = {hidden = true;};
};
"Mod+4" = {
action = focus-workspace 4;
hotkey-overlay = {hidden = true;};
};
"Mod+5" = {
action = focus-workspace 5;
hotkey-overlay = {hidden = true;};
};
"Mod+6" = {
action = focus-workspace 6;
hotkey-overlay = {hidden = true;};
};
"Mod+7" = {
action = focus-workspace 7;
hotkey-overlay = {hidden = true;};
};
"Mod+8" = {
action = focus-workspace 8;
hotkey-overlay = {hidden = true;};
};
"Mod+9" = {
action = focus-workspace 9;
hotkey-overlay = {hidden = true;};
};
"Mod+0" = {
action = focus-workspace 10;
hotkey-overlay = {hidden = true;};
};
"Mod+Shift+1" = {
action.move-window-to-workspace = 1;
hotkey-overlay = {title = "Move current window to workspace 1. Equivalent bindings for other workspaces.";};
};
"Mod+Shift+2" = {
action.move-window-to-workspace = 2;
hotkey-overlay = {hidden = true;};
};
"Mod+Shift+3" = {
action.move-window-to-workspace = 3;
hotkey-overlay = {hidden = true;};
};
"Mod+Shift+4" = {
action.move-window-to-workspace = 4;
hotkey-overlay = {hidden = true;};
};
"Mod+Shift+5" = {
action.move-window-to-workspace = 5;
hotkey-overlay = {hidden = true;};
};
"Mod+Shift+6" = {
action.move-window-to-workspace = 6;
hotkey-overlay = {hidden = true;};
};
"Mod+Shift+7" = {
action.move-window-to-workspace = 7;
hotkey-overlay = {hidden = true;};
};
"Mod+Shift+8" = {
action.move-window-to-workspace = 8;
hotkey-overlay = {hidden = true;};
};
"Mod+Shift+9" = {
action.move-window-to-workspace = 9;
hotkey-overlay = {hidden = true;};
};
"Mod+Shift+0" = {
action.move-window-to-workspace = 10;
hotkey-overlay = {hidden = true;};
};
};
};
};
};
};
}

View File

@ -0,0 +1,265 @@
{color}: {
enable = false;
settings = {
# configure noctalia here; defaults will
# be deep merged with these attributes.
colorSchemes.predefinedScheme = "Catppuccin";
general = {
avatarImage = ../../../config/face.jpeg;
radiusRatio = 0.2;
showScreenCorners = false;
forceBlackScreenCorners = false;
dimDesktop = true;
scaleRatio = 1;
screenRadiusRatio = 1;
animationSpeed = 1;
animationDisabled = false;
compactLockScreen = false;
lockOnSuspend = true;
enableShadows = true;
shadowDirection = "bottom_right";
shadowOffsetX = 2;
shadowOffsetY = 3;
language = "";
};
ui = {
fontDefault = color.font;
fontFixed = color.font;
tooltipsEnabled = true;
panelsAttachedToBar = true;
settingsPanelAttachTobar = true;
fontDefaultScale = 1;
fontFixedScale = 1;
settingsPanelAttachToBar = false;
};
location = {
name = "Dortmund, Germany";
monthBeforeDay = true;
weatherEnabled = true;
useFahrenheit = false;
use12hourFormat = false;
showWeekNumberInCalendar = false;
showCalendarEvents = true;
showCalendarWeather = true;
analogClockInCalendar = false;
firstDayOfWeek = -1;
};
screenRecorder = {
directory = "~/Videos/Recordings";
frameRate = 60;
audioCodec = "aac";
videoCodec = "h265";
quality = "very_high";
colorRange = "limited";
showCursor = true;
audioSource = "default_output";
videoSource = "portal";
};
wallpaper = {
enabled = true;
overviewEnabled = true;
directory = "~/NixFlake/wallpapers";
enableMultiMonitorDirectories = false;
recursiveSearch = false;
setWallpaperOnAllMonitors = true;
defaultWallpaper = ../../../wallpapers/Windows.jpg;
fillMode = "crop";
fillColor = "#000000";
randomEnabled = false;
randomIntervalSec = 300;
transitionDuration = 1500;
transitionType = "random";
transitionEdgeSmoothness = 0.05;
monitors = [];
panelPosition = "follow_bar";
};
appLauncher = {
enableClipboardHistory = true;
position = "center";
backgroundOpacity = 1;
pinnedExecs = [];
useApp2Unit = false;
sortByMostUsed = true;
terminalCommand = "kitty -e";
customLaunchPrefixEnabled = false;
customLaunchPrefix = "";
};
dock = {
enabled = false;
};
network = {
wifiEnabled = true;
bluetoothEnabled = true;
};
notifications = {
enabled = true;
monitors = [];
location = "top_right";
overlayLayer = true;
backgroundOpacity = 1;
respectExpireTimeout = false;
lowUrgencyDuration = 3;
normalUrgencyDuration = 8;
criticalUrgencyDuration = 15;
};
osd = {
enabled = true;
location = "top_right";
monitors = [];
autoHideMs = 2000;
overlayLayer = true;
};
audio = {
volumeStep = 5;
volumeOverdrive = true;
cavaFrameRate = 30;
visualizerType = "linear";
visualizerQuality = "high";
mprisBlacklist = [];
preferredPlayer = "";
externalMixer = "kitty --title=Ncpamixer ncpamixer";
};
nightLight = {
enabled = false;
forced = false;
autoSchedule = true;
nightTemp = "5000";
dayTemp = "6500";
manualSunrise = "06:30";
manualSunset = "21:30";
};
sessionMenu = {
countdownDuration = 10000;
enableCountdown = true;
position = "center";
powerOptions = [
{
action = "lock";
enabled = true;
}
{
action = "suspend";
enabled = false;
}
{
action = "reboot";
enabled = true;
}
{
action = "logout";
enabled = true;
}
{
action = "shutdown";
enabled = true;
}
];
showHeader = true;
};
bar = {
density = "default";
position = "top";
showCapsule = false;
outerCorners = false;
exclusive = true;
backgroundOpacity = 1;
monitors = [];
floating = false;
marginVertical = 0.25;
marginHorizontal = 0.25;
widgets = {
left = [
{
id = "SidePanelToggle";
useDistroLogo = true;
}
{
hideUnoccupied = false;
id = "Workspace";
labelMode = "none";
}
{
id = "ActiveWindow";
maxWidth = 250;
}
];
center = [
{
id = "MediaMini";
maxWidth = 250;
showAlbumArt = true;
}
{
id = "AudioVisualizer";
width = 100;
visualizerType = "mirrored";
}
];
right = [
# {
# id = "SystemMonitor";
# usePrimaryColor = true;
# showCpuUsage = true;
# showCpuTemp = false;
# showMemoryUsage = true;
# showMemoryAsPercent = false;
# showNetworkStats = true;
# showDiskUsage = true;
# diskPath = "/";
# }
{
id = "Volume";
# displayMode = "alwaysShow";
}
{
id = "Microphone";
# displayMode = "alwaysShow";
}
{
id = "Bluetooth";
# displayMode = "alwaysShow";
}
{
id = "WiFi";
# displayMode = "alwaysShow";
}
{
id = "VPN";
# displayMode = "alwaysShow";
}
{
id = "Tray";
drawerEnabled = false;
}
{
formatHorizontal = "yyyy-MM-dd HH:mm";
formatVertical = "HH mm";
id = "Clock";
useMonospacedFont = true;
usePrimaryColor = true;
}
{
id = "NotificationHistory";
}
];
};
};
};
}

View File

@ -0,0 +1,7 @@
{
lib,
mylib,
...
}: {
enable = lib.mkEnableOption "Niri";
}

View File

@ -0,0 +1,86 @@
# TODO: Expose some settings
{
config,
lib,
mylib,
pkgs,
...
}: let
inherit (config.modules) nnn;
in {
options.modules.nnn = import ./options.nix {inherit lib mylib;};
config = lib.mkIf nnn.enable {
home.sessionVariables = {
# NNN_TERMINAL = "alacritty";
# NNN_FIFO = "/tmp/nnn.fifo"; # For nnn preview
NNN_PAGER = "bat";
NNN_OPENER = "xdg-open";
NNN_ARCHIVE = "\\.(7z|a|ace|alz|arc|arj|bz|bz2|cab|cpio|deb|gz|jar|lha|lz|lzh|lzma|lzo|rar|rpm|rz|t7z|tar|tbz|tbz2|tgz|tlz|txz|tZ|tzo|war|xpi|xz|Z|zip)$";
};
programs.nnn = {
package = pkgs.nnn.override {
# These two are mutually exclusive
withIcons = false;
withNerdIcons = true;
};
enable = true;
extraPackages = with pkgs; [
xdragon # Drag and drop (why man)
];
bookmarks = {
b = "~/";
c = "~/.config";
d = "~/Documents";
D = "~/Downloads";
# h = "~/Notes/HHU";
# l = "~/Local";
# m = "~/Mount";
# n = "~/Notes";
N = "~/NixFlake";
# p = "~/Pictures";
t = "~/Notes/TU";
# v = "~/Videos";
};
plugins = {
mappings = {
c = "fzcd";
d = "dragdrop";
# f = "finder";
j = "autojump";
# k = "kdeconnect";
p = "preview-tui";
# s = "suedit";
# s = "x2sel";
v = "imgview";
};
src =
(pkgs.fetchFromGitHub {
owner = "jarun";
repo = "nnn";
rev = "33126ee813ed92726aa66295b9771ffe93e7ff0a";
sha256 = "sha256-g19uI36HyzTF2YUQKFP4DE2ZBsArGryVHhX79Y0XzhU=";
})
+ "/plugins";
};
};
xdg.desktopEntries.nnn = {
type = "Application";
name = "nnn";
comment = "Terminal file manager";
exec = "nnn";
terminal = true;
icon = "nnn";
mimeType = ["inode/directory"];
categories = ["System" "FileTools" "FileManager" "ConsoleOnly"];
# keywords = ["File" "Manager" "Management" "Explorer" "Launcher"];
};
};
}

View File

@ -0,0 +1,9 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
enable = mkEnableOption "NNN File Manager";
}

View File

@ -0,0 +1,15 @@
{
config,
nixosConfig,
lib,
mylib,
pkgs,
...
}: let
inherit (config) paths;
in {
# The paths module doesn't use the "modules" namespace to keep the access shorter
options.paths = import ./options.nix {inherit lib mylib;};
config = {};
}

View File

@ -0,0 +1,21 @@
{
lib,
mylib,
...
}:
with lib;
with mylib.modules; {
nixflake = lib.mkOption {
type = lib.types.path;
apply = toString;
example = "${config.home.homeDirectory}/NixFlake";
description = "Location of the NixFlake working copy";
};
dotfiles = lib.mkOption {
type = lib.types.path;
apply = toString;
example = "${config.home.homeDirectory}/NixFlake/config";
description = "Location of the NixFlake working copy's config directory";
};
}

View File

@ -0,0 +1,193 @@
{color}: {
webpage.darkmode.enabled = true;
completion = {
## Background color of the completion widget category headers.
category.bg = color.hexS.base;
category.fg = color.hexS.accent;
## Bottom border color of the completion widget category headers.
category.border.top = color.hexS.base;
category.border.bottom = color.hexS.accent;
## Background color of the completion widget for even and odd rows.
even.bg = color.hexS.base;
odd.bg = color.hexS.base;
## Text color of the completion widget.
fg = color.hexS.text;
# Selected item color + border
item.selected.bg = color.hexS.accent;
item.selected.fg = color.hexS.accentText;
item.selected.border.bottom = color.hexS.surface2;
item.selected.border.top = color.hexS.surface2;
## Foreground color of the selected completion item.
item.selected.match.fg = color.hexS.accentText;
## Foreground color of the matched text in the completion.
match.fg = color.hexS.accent;
## Color of the scrollbar in completion view
scrollbar.bg = color.hexS.base;
scrollbar.fg = color.hexS.accent;
};
downloads = {
bar.bg = color.hexS.base;
error.bg = color.hexS.base;
error.fg = color.hexS.red;
# Color gradient
start.bg = color.hexS.base;
start.fg = color.hexS.blue;
stop.bg = color.hexS.base;
stop.fg = color.hexS.green;
# Set to "none" to disable gradient, otherwise "rgb"
system.fg = "none";
system.bg = "none";
};
hints = {
## Background color for hints. Note that you can use a `rgba(...)` value
## for transparency.
bg = color.hexS.accentDim;
fg = color.hexS.accentText;
## Font color for the matched part of hints.
match.fg = color.hexS.accent;
};
keyhint = {
## Background color of the keyhint widget.
bg = color.hexS.accentDim;
fg = color.hexS.accentText;
## Highlight color for keys to complete the current keychain.
suffix.fg = color.hexS.accent;
};
messages = {
## Background color of an error message.
error.bg = color.hexS.base;
error.fg = color.hexS.red;
error.border = color.hexS.red;
## Background color of an info message.
info.bg = color.hexS.base;
info.fg = color.hexS.blue;
info.border = color.hexS.blue;
## Background color of a warning message.
warning.bg = color.hexS.base;
warning.fg = color.hexS.yellow;
warning.border = color.hexS.yellow;
};
prompts = {
## Background color for prompts.
bg = color.hexS.base;
fg = color.hexS.text;
# ## Border used around UI elements in prompts.
border = "1px solid " + color.hexS.overlay0;
## Background color for the selected item in filename prompts.
selected.bg = color.hexS.accent;
selected.fg = color.hexS.accentText;
};
statusbar = {
## Background color of the statusbar.
normal.bg = color.hexS.base;
normal.fg = color.hexS.text;
## Background color of the statusbar in insert mode.
insert.bg = color.hexS.green;
insert.fg = color.hexS.accentText;
## Background color of the statusbar in command mode.
command.bg = color.hexS.peach;
command.fg = color.hexS.accentText;
## Background color of the statusbar in caret mode.
caret.bg = color.hexS.blue;
caret.fg = color.hexS.accentText;
## Background color of the statusbar in caret mode with a selection.
caret.selection.bg = color.hexS.blue;
caret.selection.fg = color.hexS.accentText;
## Background color of the progress bar.
progress.bg = color.hexS.base;
## Background color of the statusbar in passthrough mode.
passthrough.bg = color.hexS.red;
passthrough.fg = color.hexS.accentText;
## Default foreground color of the URL in the statusbar.
# NOTE: The colors will be barely legible in different modes,
# but currently we can't change url color per mode...
url.fg = color.hexS.text;
url.warn.fg = color.hexS.yellow;
url.error.fg = color.hexS.red;
url.hover.fg = color.hexS.sky;
url.success.http.fg = color.hexS.red;
url.success.https.fg = color.hexS.green;
## PRIVATE MODE COLORS
## Background color of the statusbar in private browsing mode.
private.bg = color.hexS.teal;
private.fg = color.hexS.accentText;
## Background color of the statusbar in private browsing + command mode.
command.private.bg = color.hexS.peach;
command.private.fg = color.hexS.accentText;
};
tabs = {
## Background color of the tab bar.
bar.bg = color.hexS.base;
# ## Background color of selected even tabs.
selected.even.bg = color.hexS.accent;
selected.even.fg = color.hexS.accentText;
# ## Background color of selected odd tabs.
selected.odd.bg = color.hexS.accent;
selected.odd.fg = color.hexS.accentText;
## Background color of unselected even tabs.
even.bg = color.hexS.base;
even.fg = color.hexS.accent;
## Background color of unselected odd tabs.
odd.bg = color.hexS.base;
odd.fg = color.hexS.accent;
## Color for the tab indicator on errors.
indicator.error = color.hexS.red;
## Color gradient interpolation system for the tab indicator.
## Valid values:
## - rgb: Interpolate in the RGB color system.
## - hsv: Interpolate in the HSV color system.
## - hsl: Interpolate in the HSL color system.
## - none: Don't show a gradient.
indicator.system = "none";
};
contextmenu = {
menu.bg = color.hexS.base;
menu.fg = color.hexS.accent;
disabled.bg = color.hexS.base;
disabled.fg = color.hexS.text;
selected.bg = color.hexS.accent;
selected.fg = color.hexS.accentText;
};
}

View File

@ -0,0 +1,181 @@
{
config,
nixosConfig,
lib,
mylib,
pkgs,
...
}: let
inherit (config.modules) qutebrowser color;
in {
options.modules.qutebrowser = import ./options.nix {inherit lib mylib;};
config = lib.mkIf qutebrowser.enable {
programs.qutebrowser = {
enable = true;
loadAutoconfig = true; # Load settings set from GUI
# TODO: Find a unified version for qutebrowser + firefox (+ other browers ideally)
quickmarks = let
# Use this function to keep the quickmarks (almost) compatible with the firefox bookmarks
mkBm = name: value: {
${name} = value;
};
in
lib.mergeAttrsList [
(mkBm "Package Search" "https://search.nixos.org/packages")
(mkBm "Option Search" "https://search.nixos.org/options?")
(mkBm "Function Search" "https://noogle.dev/")
(mkBm "HM Search" "https://mipmip.github.io/home-manager-option-search/")
(mkBm "NUR Search" "https://nur.nix-community.org/")
(mkBm "Nixpkgs Version Search" "https://lazamar.co.uk/nix-versions/")
(mkBm "Nixpkgs PR Tracker" "https://nixpk.gs/pr-tracker.html")
(mkBm "NixOS Wiki" "https://wiki.nixos.org/wiki/NixOS_Wiki")
(mkBm "Nixpkgs Issues" "https://github.com/NixOS/nixpkgs/issues")
(mkBm "Nixpkgs Manual" "https://nixos.org/manual/nixpkgs/unstable/")
(mkBm "NixOS Manual" "https://nixos.org/manual/nixos/unstable/")
(mkBm "Nix Manual" "https://nix.dev/manual/nix/stable/")
(mkBm "Searchix" "https://searchix.ovh/")
(mkBm "Latest" "https://discourse.nixos.org/latest")
(mkBm "LAN Smart Switch" "http://192.168.86.2/")
(mkBm "WiFi Access Point" "http://192.168.86.3/")
(mkBm "OPNsense" "https://192.168.86.5/")
(mkBm "Synology DS223j" "https://synology.think.chriphost.de/")
(mkBm "PVE Direct" "https://192.168.86.4:8006/#v1:0:18:4:::::::")
(mkBm "PVF Direct" "https://192.168.86.13:8006/#v1:0:18:4:::::::")
(mkBm "Portainer" "https://portainer.think.chriphost.de/")
(mkBm "Local NGINX" "https://nginx.local.chriphost.de/")
(mkBm "Think NGINX" "https://nginx.think.chriphost.de/")
(mkBm "VPS NGINX" "http://vps.chriphost.de:51810/")
(mkBm "WUD ServeNix" "https://update.local.chriphost.de/")
(mkBm "WUD ThinkNix" "https://update.think.chriphost.de/")
(mkBm "Cloud" "https://nextcloud.local.chriphost.de/apps/files/files")
(mkBm "Immich" "https://immich.local.chriphost.de/photos")
(mkBm "Jelly" "https://jellyfin.local.chriphost.de/web/#/home.html")
(mkBm "HASS" "https://hass.think.chriphost.de/lovelace")
(mkBm "Docs" "https://paperless.local.chriphost.de/documents?sort=created&reverse=1&page=1")
(mkBm "Gitea" "https://gitea.local.chriphost.de/christoph")
# (mkBm "Chat" "http://localhost:11435/") # Local WebUI
(mkBm "C++Ref" "https://en.cppreference.com/w/")
(mkBm "Rust" "https://doc.rust-lang.org/stable/book/ch03-00-common-programming-concepts.html")
(mkBm "RustOS" "https://os.phil-opp.com/")
(mkBm "Interpreters" "https://craftinginterpreters.com/contents.html")
(mkBm "Mistral Chat" "https://chat.mistral.ai/chat")
(mkBm "DeepSeek Chat" "https://chat.deepseek.com/")
(mkBm "Claude Chat" "https://claude.ai/new")
(mkBm "ChatGPT" "https://chatgpt.com/")
(mkBm "DeepWiki" "https://deepwiki.com/")
(mkBm "Mistral API" "https://console.mistral.ai/usage")
(mkBm "DeepSeek API" "https://platform.deepseek.com/usage")
(mkBm "Claude API" "https://console.anthropic.com/usage")
(mkBm "OpenRouter API" "https://openrouter.ai/activity")
(mkBm "GH" "https://github.com/churl")
(mkBm "GL" "https://gitlab.com/churl")
(mkBm "SO" "https://stackoverflow.com/users/saves/17337508/all")
(mkBm "RegEx" "https://regex101.com/")
(mkBm "Shell" "https://explainshell.com/")
(mkBm "CDecl" "https://cdecl.org/")
(mkBm "ECR" "https://gallery.ecr.aws/")
(mkBm "Chmod" "https://chmod-calculator.com/")
(mkBm "Spiegel" "https://www.spiegel.de/")
(mkBm "Heise" "https://www.heise.de/")
(mkBm "HN" "https://news.ycombinator.com/news")
(mkBm "Reddit" "https://www.reddit.com/user/FightingMushroom/saved/")
(mkBm "F10" "https://f10.local.chriphost.de/race/Everyone")
(mkBm "F11" "https://f11.local.chriphost.de/racepicks")
(mkBm "F11PB" "https://f11pb.local.chriphost.de/_/#/collections?collection=pbc_1736455494&filter=&sort=-%40rowid")
(mkBm "ISBNDB" "https://isbndb.com/")
(mkBm "Music" "https://bandcamp.com/chriphost")
(mkBm "Albums" "https://www.albumoftheyear.org/user/chriphost/list/307966/2025/")
];
# TODO: Find a unified version for qutebrowser + firefox (+ other browsers ideally)
searchEngines = {
DEFAULT = "https://kagi.com/search?q={}";
k = "https://kagi.com/search?q={}";
w = "https://en.wikipedia.org/wiki/Special:Search?search={}";
np = "https://searchix.ovh/?query={}";
nf = "https://noogle.dev/q?term={}";
nw = "https://wiki.nixos.org/index.php?search={}";
aw = "https://wiki.archlinux.org/?search={}";
i = "https://github.com/NixOS/nixpkgs/issues?q=is%3Aissue%20{}";
gh = "https://github.com/search?q={}&type=repositories";
g = "https://www.google.com/search?hl=en&q={}";
};
# greasemonkey = [];
# Map keys to other keys
# keyMappings = {};
# Map keys to commands
# keyBindings = {
# normal = {
# "<Ctrl-v>" = "spawn mpv {url}";
# ",p" = "spawn --userscript qute-pass";
# ",l" = ''config-cycle spellcheck.languages ["en-GB"] ["en-US"]'';
# "<F1>" = lib.mkMerge [
# "config-cycle tabs.show never always"
# "config-cycle statusbar.show in-mode always"
# "config-cycle scrolling.bar never always"
# ];
# };
# prompt = {
# "<Ctrl-y>" = "prompt-yes";
# };
# };
enableDefaultBindings = true;
settings = {
# Theme
colors = import ./colors.nix {inherit color;};
fonts = {
default_family = color.font;
default_size = "12pt";
web.family.fixed = color.font;
};
hints.border = "1px solid " + color.hexS.mantle;
# Settings
auto_save.session = true;
changelog_after_upgrade = "minor";
completion.height = "33%";
content = {
autoplay = true;
blocking.enabled = true;
blocking.method = "auto"; # "auto", "adblock", "hosts", "both"
dns_prefetch = true;
};
editor.command = ["neovide" "{file}" "--" "normal {line}G{column0}l"];
# TODO: termfilechooser, also for downloads (those are separate)
# fileselect = {
# handler = "external";
# folder.command = [];
# multiple_files.command = [];
# single_file.command = [];
# };
input.media_keys = false;
prompt.radius = 6;
scrolling.smooth = true;
session.lazy_restore = true;
tabs.position = "right";
url = {
default_page = "about:blank";
open_base_url = true;
start_pages = ["https://kagi.com"];
};
};
# Same keys as qutebrowser.settings, but per domain
# perDomainSettings = {
# "github.com".colors.webpage.darkmode.enabled = false;
# };
};
};
}

View File

@ -0,0 +1,7 @@
{
lib,
mylib,
...
}: {
enable = lib.mkEnableOption "TEMPLATE";
}

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