Move some (all) files around

Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
2024-07-08 20:01:55 +03:00
parent 9dfbe1203d
commit 7ab40e3493
103 changed files with 202 additions and 217 deletions

View File

@@ -1,7 +0,0 @@
{
programs.ssh = {
knownHosts = {
eirene.publicKeyFile = ../../../eirene/secrets/ssh_host_ed25519_key.pub;
};
};
}

View File

@@ -1,30 +0,0 @@
{
imports = [
./configs/boot
./configs/system
./configs/nix
./configs/persist
./configs/sops
./configs/users
./configs/getty
./configs/plymouth
./configs/networking
./configs/bluetooth
./configs/brightnessctl
./configs/pipewire
./configs/zsh
./configs/neovim
./configs/tmux
./configs/ssh
./configs/nix-ld
./configs/git
./configs/gpg-agent
./configs/tree
./configs/ranger
./configs/btop
./configs/fastfetch
./scripts/cleanup
];
i18n.defaultLocale = "en_US.UTF-8";
}

View File

@@ -0,0 +1,7 @@
{
programs.ssh = {
knownHosts = {
eirene.publicKeyFile = ../../../../eirene/secrets/ssh_host_ed25519_key.pub;
};
};
}

View File

@@ -0,0 +1,31 @@
{
user ? throw "user argument is required",
}:
{
config,
lib,
pkgs,
...
}:
{
home-manager.users.${user.name}.systemd.user.services.mpris-proxy = {
Unit = {
Description = "MPRIS proxy";
Requires = [ "sound.target" ];
After = [
"network.target"
"sound.target"
];
};
Service.ExecStart = lib.meta.getExe (
pkgs.writeShellApplication {
name = "init-mpris-proxy";
runtimeInputs = with pkgs; [ bluez ];
text = "exec mpris-proxy";
}
);
Install.WantedBy = [ "default.target" ];
};
}

View File

@@ -0,0 +1,7 @@
{
user ? throw "user argument is required",
}:
{ lib, pkgs, ... }:
{
home-manager.users.${user.name}.home.packages = with pkgs; [ brightnessctl ];
}

View File

@@ -0,0 +1,19 @@
{
user ? throw "user argument is required",
}:
{ ... }:
{
home-manager.users.${user.name}.programs.btop = {
enable = true;
settings = {
theme_background = false;
presets = "";
vim_keys = true;
shown_boxes = "cpu mem net proc gpu0 gpu1";
update_ms = 1000;
proc_tree = true;
cpu_single_graph = true;
disks_filter = "/ /nix /persist /cache";
};
};
}

View File

@@ -0,0 +1,3 @@
git interpret-trailers --if-exists doNothing --trailer \
"Signed-off-by: $(git config user.name) <$(git config user.email)>" \
--in-place "$1"

View File

@@ -0,0 +1,44 @@
{
user ? throw "user argument is required",
}:
{
config,
lib,
pkgs,
...
}:
let
hmConfig = config.home-manager.users.${user.name};
in
{
home-manager.users.${user.name} = {
programs.git = {
enable = true;
lfs.enable = true;
userName = user.fullName;
userEmail = user.email;
signing = {
signByDefault = true;
key = null;
};
extraConfig = {
credential.helper = "store";
push.autoSetupRemote = true;
};
hooks = {
commit-msg = lib.meta.getExe (
pkgs.writeShellApplication {
name = "git-commit-msg-hook";
runtimeInputs = with pkgs; [ git ];
text = builtins.readFile ./commit-msg.sh;
}
);
};
};
sops.secrets."git".path = "${hmConfig.xdg.configHome}/git/credentials";
};
}

View File

@@ -0,0 +1,75 @@
{
user ? throw "user argument is required",
}:
{
config,
lib,
pkgs,
...
}:
let
hmConfig = config.home-manager.users.${user.name};
gpgPath = "${hmConfig.xdg.dataHome}/gnupg";
in
{
home-manager.users.${user.name} = {
programs.gpg = {
enable = true;
homedir = gpgPath;
};
services.gpg-agent = {
enable = true;
defaultCacheTtl = 31536000;
maxCacheTtl = 31536000;
};
systemd.user = {
services.gpg-agent-import =
let
init = lib.meta.getExe (
pkgs.writeShellApplication {
name = "import-gpg-keys";
runtimeInputs = with pkgs; [
coreutils
gnugrep
gnupg
];
runtimeEnv = {
GNUPGHOME = gpgPath;
HOME = user.home;
};
text = builtins.readFile ./import-gpg-keys.sh;
}
);
in
{
Unit = {
Description = "Auto-import GPG keys";
Requires = [
"sops-nix.service"
"gpg-agent.socket"
];
After = [
"sops-nix.service"
"gpg-agent.socket"
];
};
Service = {
Type = "oneshot";
ExecStart = init;
};
Install.WantedBy = [ "default.target" ];
};
tmpfiles.rules = [ "d ${gpgPath} 0700 ${user.name} users -" ];
};
sops.secrets = {
"gpg-agent/pgp.key" = { };
"gpg-agent/pgp.pass" = { };
};
};
}

View File

@@ -0,0 +1,16 @@
for keyfile in "$HOME"/.config/sops-nix/secrets/gpg-agent/*.key; do
passfile="${keyfile%.key}.pass"
if [ -f "$passfile" ]; then
gpg2 --batch --yes --pinentry-mode loopback --passphrase-file "$passfile" --import "$keyfile"
else
gpg2 --batch --yes --import "$keyfile"
fi
gpg2 --with-colons --import-options show-only --import "$keyfile" | grep '^fpr' | cut -d: -f10 | while read -r KEY_ID; do
echo "$KEY_ID:6:" >> "$GNUPGHOME"/otrust.txt
done
done
gpg2 --import-ownertrust "$GNUPGHOME"/otrust.txt
rm "$GNUPGHOME"/otrust.txt

View File

@@ -0,0 +1,26 @@
{
user ? throw "user argument is required",
}:
{ config, inputs, ... }:
{
imports = [
inputs.home-manager.nixosModules.default
];
programs.dconf.enable = true;
home-manager = {
extraSpecialArgs = {
inherit inputs;
};
backupFileExtension = "bak";
useGlobalPkgs = true;
users.${user.name} = {
home.stateVersion = "24.05";
systemd.user.startServices = "sd-switch";
nix.settings = config.nix.settings;
nixpkgs.config = config.nixpkgs.config;
};
};
}

View File

@@ -0,0 +1,21 @@
{
user ? throw "user argument is required",
}:
{ ... }:
{
home-manager.users.${user.name} = {
programs.neovim = {
enable = true;
defaultEditor = true;
viAlias = true;
vimAlias = true;
vimdiffAlias = true;
extraConfig = ''
set tabstop=2
set shiftwidth=2
set expandtab
set smartindent
'';
};
};
}

View File

@@ -0,0 +1,30 @@
{
user ? throw "user argument is required",
}:
{
config,
inputs,
lib,
...
}:
{
programs.fuse.userAllowOther = true;
systemd.tmpfiles.rules = (
[
"d /persist/home 0755 root root -"
"d /cache/home 0755 root root -"
"d /persist${user.home} 0700 ${user.name} users -"
"d /cache${user.home} 0700 ${user.name} users -"
]
);
home-manager.users.${user.name} = {
imports = [ inputs.impermanence.nixosModules.home-manager.impermanence ];
home.persistence = {
"/persist${user.home}".allowOther = true;
"/cache${user.home}".allowOther = true;
};
};
}

View File

@@ -0,0 +1,13 @@
{
user ? throw "user argument is required",
}:
{ pkgs, ... }:
{
home-manager.users.${user.name} = {
home.packages = with pkgs; [
wireplumber
playerctl
];
services.playerctld.enable = true;
};
}

View File

@@ -0,0 +1,24 @@
{
user ? throw "user argument is required",
}:
{
config,
inputs,
lib,
...
}:
let
sopsKeyPath = ".config/sops-nix/key.txt";
in
{
home-manager.users.${user.name} = {
imports = [ inputs.sops-nix.homeManagerModules.sops ];
sops.age.keyFile = "/persist${user.home}/${sopsKeyPath}";
home = {
persistence."/persist${user.home}".files = [ sopsKeyPath ];
sessionVariables.SOPS_AGE_KEY_FILE = "${user.home}/${sopsKeyPath}";
};
};
}

View File

@@ -0,0 +1,35 @@
{
user ? throw "user argument is required",
}:
{ config, ... }:
{
networking.firewall = {
allowedTCPPorts = [ 22000 ];
allowedUDPPorts = [
21027
22000
];
};
sops.secrets = {
# openssl ecparam -name prime256v1 -genkey -noout -out key.pem
"syncthing/key" = {
owner = user.name;
group = "users";
};
# openssl req -new -x509 -key key.pem -out cert.pem -days 3650
"syncthing/cert" = {
owner = user.name;
group = "users";
};
};
home-manager.users.${user.name}.services.syncthing = {
enable = true;
key = config.sops.secrets."syncthing/key".path;
cert = config.sops.secrets."syncthing/cert".path;
extraOptions = [ "-no-default-folder" ];
settings.options.urAccepted = -1;
};
}

View File

@@ -0,0 +1,34 @@
{
user ? throw "user argument is required",
}:
{ config, lib, ... }:
{
home-manager.users.${user.name} = {
imports = [ ./options.nix ];
xdg = {
enable = true;
mimeApps.enable = true;
userDirs = {
enable = true;
extraConfig = {
XDG_VM_DIR = "${user.home}/VMs";
XDG_GIT_DIR = "${user.home}/git";
};
};
};
home.persistence."/persist${user.home}".directories = [
"Desktop" # userDirs.desktop
"Documents" # userDirs.documents
"Downloads" # userDirs.download
"Music" # userDirs.music
"Pictures" # userDirs.pictures
"Templates" # userDirs.templates
"Videos" # userDirs.videos
"VMs"
"git"
];
};
}

View File

@@ -0,0 +1,42 @@
{ config, lib, ... }:
let
cfg = config.xdg;
in
{
options.xdg =
with lib;
with types;
{
relativeCacheHome = mkOption {
type = str;
default = ".cache";
description = "Relative path to directory holding application caches.";
};
cacheHome = mkOption { default = "${config.home.homeDirectory}/${cfg.relativeCacheHome}"; };
relativeConfigHome = mkOption {
type = str;
default = ".config";
description = "Relative path to directory holding application configurations.";
};
configHome = mkOption { default = "${config.home.homeDirectory}/${cfg.relativeConfigHome}"; };
relativeDataHome = mkOption {
type = str;
default = ".local/share";
description = "Relative path to directory holding application data.";
};
dataHome = mkOption { default = "${config.home.homeDirectory}/${cfg.relativeDataHome}"; };
relativeStateHome = mkOption {
type = str;
default = ".local/state";
description = "Relative path to directory holding application states.";
};
stateHome = mkOption { default = "${config.home.homeDirectory}/${cfg.relativeStateHome}"; };
};
}

View File

@@ -0,0 +1,25 @@
{
user ? throw "user argument is required",
}:
{ config, ... }:
let
hmConfig = config.home-manager.users.${user.name};
in
{
home-manager.users.${user.name} = {
programs.zsh = {
enable = true;
dotDir = "${hmConfig.xdg.relativeConfigHome}/zsh";
autocd = true;
history = {
path = "${hmConfig.xdg.dataHome}/zsh/history";
expireDuplicatesFirst = true;
};
historySubstringSearch.enable = true;
autosuggestion.enable = true;
syntaxHighlighting.enable = true;
};
home.persistence."/persist${user.home}".directories = [ "${hmConfig.xdg.relativeDataHome}/zsh" ];
};
}

View File

@@ -0,0 +1,3 @@
node_modules
types
bun.lockb

View File

@@ -0,0 +1,7 @@
{
"arrowParens": "avoid",
"bracketSameLine": true,
"bracketSpacing": true,
"singleQuote": true,
"trailingComma": "all"
}

View File

@@ -0,0 +1,27 @@
{
pkgs ? import <nixpkgs> { },
...
}:
pkgs.stdenv.mkDerivation {
name = "ags-config";
src = ./.;
nativeBuildInputs = with pkgs; [ bun ];
phases = [
"buildPhase"
"installPhase"
];
buildPhase = ''
bun build $src/src/index.ts --outfile=index.js \
--external="file://$src/*" \
--external="gi://*"
'';
installPhase = ''
mkdir -p $out/share
cp index.js $out/share/config.js
'';
}

View File

@@ -0,0 +1,116 @@
/* eslint no-use-before-define: 0 */
import globals from 'globals';
import pluginJs from '@eslint/js';
import tseslint from 'typescript-eslint';
import typescriptEslint from '@typescript-eslint/eslint-plugin';
import unicorn from 'eslint-plugin-unicorn';
import prettier from 'eslint-plugin-prettier';
import tsParser from '@typescript-eslint/parser';
export default [
{ files: ['**/*.{js,mjs,cjs,ts}'] },
{ languageOptions: { globals: globals.browser } },
pluginJs.configs.recommended,
...tseslint.configs.recommended,
{
plugins: {
'@typescript-eslint': typescriptEslint,
unicorn,
prettier,
},
languageOptions: {
globals: {
...globals.browser,
},
parser: tsParser,
ecmaVersion: 5,
sourceType: 'script',
parserOptions: {
project: ['./tsconfig.json'],
},
},
settings: {
'import/resolver': {
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
},
},
rules: {
curly: ['error', 'multi-line'],
'eol-last': ['error', 'always'],
semi: ['error', 'always'],
quotes: ['error', 'single'],
'no-await-in-loop': 'warn',
'no-constructor-return': 'error',
'no-duplicate-imports': 'error',
'no-self-compare': 'error',
'no-unreachable-loop': 'error',
'no-trailing-spaces': 'error',
'no-console': 'warn',
'no-shadow': 'off',
'@typescript-eslint/no-shadow': ['error'],
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': ['error'],
'no-use-before-define': 'off',
'@typescript-eslint/no-use-before-define': ['error'],
'@typescript-eslint/require-await': 'warn',
'@typescript-eslint/no-misused-promises': ['error', {
checksVoidReturn: false,
}],
'@typescript-eslint/naming-convention': [
'error',
{
selector: 'default',
format: ['camelCase'],
leadingUnderscore: 'allowSingleOrDouble',
},
{
selector: 'variableLike',
format: ['camelCase', 'PascalCase'],
leadingUnderscore: 'allowSingleOrDouble',
},
{
selector: 'memberLike',
format: ['camelCase'],
},
{
selector: 'typeLike',
format: ['PascalCase'],
},
{
selector: 'property',
format: ['snake_case'],
},
{
selector: 'method',
format: ['camelCase'],
},
{
selector: ['enumMember', 'enum'],
format: ['UPPER_CASE'],
}
],
'unicorn/empty-brace-spaces': 'off',
'unicorn/expiring-todo-comments': 'off',
'unicorn/no-array-for-each': 'off',
'unicorn/filename-case': ['error', {
case: 'camelCase',
}],
'unicorn/numeric-separators-style': 'off',
'unicorn/prevent-abbreviations': 'off',
},
"ignores": ["*.config.js"]
}
];

View File

@@ -0,0 +1,23 @@
{
"name": "ags",
"module": "index.ts",
"type": "module",
"scripts": {
"lint": "eslint ."
},
"devDependencies": {
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.6.0",
"@types/bun": "^1.1.6",
"@typescript-eslint/eslint-plugin": "^7.14.1",
"@typescript-eslint/parser": "^7.14.1",
"eslint": "9.x",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-unicorn": "^54.0.0",
"globals": "^15.6.0",
"typescript-eslint": "^7.14.1"
},
"peerDependencies": {
"typescript": "^5.0.0"
}
}

View File

@@ -0,0 +1,19 @@
import gtk from 'gi://Gtk?version=3.0';
import gdk from 'gi://Gdk';
import { range } from 'lib';
import themeInit from 'theme';
import bar from 'widgets/bar/bar';
const forMonitors = (widget: (monitor: number) => gtk.Window) => {
const n = gdk.Display.get_default()?.get_n_monitors() || 1;
return range(n, 0).flatMap(widget);
};
App.config({
style: themeInit(),
windows: [
...forMonitors(bar),
]
});
Utils.execAsync('systemd-notify --ready')

View File

@@ -0,0 +1,3 @@
export const range = (length: number, start = 1) => {
return Array.from({ length }, (n, i) => i + start);
};

View File

@@ -0,0 +1,25 @@
export default () => {
const css = `${App.configDir}/theme.css`;
const scss = `${App.configDir}/theme.sass`;
let themeExists = true;
try {
Utils.readFile(scss);
Utils.exec(`sassc ${scss} ${css}`);
} catch (error) {
console.error(error);
themeExists = false;
}
Utils.monitorFile(
`${App.configDir}/theme.sass`,
function () {
Utils.exec(`sassc ${scss} ${css}`);
App.resetCss();
App.applyCss(css);
},
);
return themeExists ? css : undefined;
};

View File

@@ -0,0 +1,39 @@
import gap from './gap/gap';
import launcher from './launcher/launcher';
import workspace from './workspace/workspace';
import date from './date/date';
import systray from './systray/systray';
export default (monitor: number) => Widget.Window({
monitor,
class_name: 'bar',
name: `bar${monitor}`,
exclusivity: 'exclusive',
anchor: ['top', 'right', 'left'],
child: Widget.CenterBox({
class_name: 'widgets',
start_widget: Widget.Box({
hexpand: true,
hpack: 'start',
children: [
launcher(),
gap(),
workspace(),
],
}),
center_widget: Widget.Box({
hexpand: true,
hpack: 'center',
children: [
date(),
],
}),
end_widget: Widget.Box({
hexpand: true,
hpack: 'end',
children: [
systray(),
],
}),
}),
});

View File

@@ -0,0 +1,10 @@
const icon = () => Widget.Icon({
class_name: 'icon',
icon: 'edit-paste-symbolic',
});
export default () => Widget.EventBox({
class_name: 'clipboard',
child: icon(),
onPrimaryClick: () => Utils.execAsync('bash -c "cliphist list | rofi -cache-dir $XDG_CACHE_HOME/rofi -dmenu -display-columns 2 | cliphist decode | wl-copy"'),
});

View File

@@ -0,0 +1,18 @@
import glib from 'gi://GLib';
const clock = Variable(glib.DateTime.new_now_local(), {
poll: [1000, () => glib.DateTime.new_now_local()]
});
const time = Utils.derive([clock], (c) => c.format('%H:%M - %A, %d %B %Y') || '');
const label = () => Widget.Label({
class_name: 'label',
justification: 'center',
label: time.bind(),
});
export default () => Widget.EventBox({
class_name: 'date',
child: label(),
});

View File

@@ -0,0 +1,3 @@
export default () => Widget.Box({
class_name: 'gap',
});

View File

@@ -0,0 +1,10 @@
const icon = () => Widget.Icon({
class_name: 'icon',
icon: 'nix-snowflake-symbolic',
});
export default () => Widget.EventBox({
class_name: 'launcher',
child: icon(),
onPrimaryClick: () => Utils.execAsync('bash -c "rofi -cache-dir $XDG_CACHE_HOME/rofi -show drun"'),
});

View File

@@ -0,0 +1,16 @@
import gdk from 'gi://Gdk';
const systemtray = await Service.import('systemtray');
const systrayItem = item => Widget.EventBox({
class_name: 'item',
tooltip_markup: item.bind('tooltip_markup'),
child: Widget.Icon({ class_name: 'icon' }).bind('icon', item, 'icon'),
onPrimaryClick: (_, event: gdk.Event) => item.activate(event),
onSecondaryClick: (_, event: gdk.Event) => item.openMenu(event),
});
export default () => Widget.Box({
class_name: 'systray',
children: systemtray.bind('items').as(i => i.map(systrayItem))
});

View File

@@ -0,0 +1,23 @@
import { range } from 'lib';
const hyprland = await Service.import('hyprland');
const dispatch = ws => hyprland.messageAsync(`dispatch workspace ${ws}`);
const workspaceButton = (i: number) => Widget.Label({
class_name: 'button',
attribute: i,
vpack: 'center',
setup: self => self.hook(hyprland, () => {
self.toggleClassName('active', hyprland.active.workspace.id === i);
self.toggleClassName('occupied', (hyprland.getWorkspace(i)?.windows || 0) > 0);
}),
});
export default () => Widget.EventBox({
class_name: 'workspace',
onScrollUp: () => dispatch('e-1'),
onScrollDown: () => dispatch('e+1'),
child: Widget.Box({
children: range(10).map(workspaceButton),
}),
});

View File

@@ -0,0 +1,18 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"lib": [
"ES2022"
],
"allowJs": true,
"checkJs": true,
"strict": true,
"noImplicitAny": false,
"baseUrl": "./src",
"typeRoots": [
"./types",
],
"skipLibCheck": true,
}
}

View File

@@ -0,0 +1,73 @@
{
user ? throw "user argument is required",
}:
{
config,
lib,
pkgs,
inputs,
...
}:
let
hmConfig = config.home-manager.users.${user.name};
agsConfig = import ./config { inherit pkgs; };
in
{
home-manager.users.${user.name} = {
imports = [ inputs.ags.homeManagerModules.default ];
programs.ags.enable = true;
xdg.configFile.ags = {
source = "${agsConfig}/share/config.js";
target = "ags/config.js";
};
programs.matugen.settings.templates.ags = {
input_path = ./theme.sass;
output_path = "${hmConfig.xdg.configHome}/ags/theme.sass";
};
systemd.user = {
targets.tray.Unit = {
BindsTo = [ "ags.service" ];
After = [
"graphical-session.target"
"ags.service"
];
};
services.ags = {
Unit = {
Description = "Desktop widget shell";
BindsTo = [ "graphical-session.target" ];
After = [ "graphical-session.target" ];
};
Service = {
Type = "notify";
NotifyAccess = "all";
ExecStart = lib.meta.getExe (
pkgs.writeShellApplication {
name = "init-ags";
runtimeInputs = with pkgs; [
inputs.ags.packages.${stdenv.hostPlatform.system}.default
sassc
hyprland
nixos-icons
rofi-wayland
wl-clipboard
cliphist
libdbusmenu-gtk3
];
text = "exec ags";
}
);
};
Install.WantedBy = [ "graphical-session.target" ];
};
};
};
}

View File

@@ -0,0 +1,74 @@
.bar
background-color: {{colors.surface.default.hex}}
@mixin interactive
min-height: {{custom.font_size}}pt
border-radius: .5 * {{custom.font_size}}pt
transition: .25s
&:hover
background-color: {{colors.surface_container_high.default.hex}}
&:active
background-color: {{colors.surface_container_highest.default.hex}}
.widgets
padding: .2 * {{custom.padding}}pt
.gap
min-height: {{custom.font_size}}pt
min-width: .5 * {{custom.padding}}pt
.launcher
.clipboard
@include interactive
min-width: {{custom.font_size}}pt
.icon
font-size: {{custom.font_size}}pt
padding: 0 .3 * {{custom.padding}}pt
color: {{colors.on_surface.default.hex}}
.workspace
@include interactive
.button
font-size: 0
transition: .5s
margin: 0 .3 * {{custom.padding}}pt
background-color: {{colors.outline_variant.default.hex}}
min-width: .4 * {{custom.font_size}}pt
min-height: .4 * {{custom.font_size}}pt
border-radius: .5 * {{custom.font_size}}pt
&.occupied
background-color: {{colors.on_surface.default.hex}}
min-width: .6 * {{custom.font_size}}pt
min-height: .6 * {{custom.font_size}}pt
border-radius: .5 * {{custom.font_size}}pt
&.active
background-color: {{colors.primary.default.hex}}
min-width: 1.67 * {{custom.font_size}}pt
min-height: {{custom.font_size}}pt
border-radius: .4 * {{custom.font_size}}pt
.date
@include interactive
.label
color: {{colors.on_surface.default.hex}}
font-size: {{custom.font_size}}pt
font-family: {{custom.font_sans_serif_all}}
font-weight: 500
margin: 0 .5 * {{custom.padding}}pt
.systray
.item
@include interactive
.icon
font-size: {{custom.font_size}}pt
padding: 0 .3 * {{custom.padding}}pt
color: {{colors.on_surface.default.hex}}

View File

@@ -0,0 +1,17 @@
{
user ? throw "user argument is required",
}:
{
config,
lib,
pkgs,
...
}:
{
services.blueman.enable = true;
home-manager.users.${user.name} = {
services.blueman-applet.enable = true;
systemd.user.services.blueman-applet.Unit.After = [ "graphical-session.target" ];
};
}

View File

@@ -0,0 +1,14 @@
{
user ? throw "user argument is required",
}:
{ lib, pkgs, ... }:
{
home-manager.users.${user.name}.wayland.windowManager.hyprland.settings.bindle =
let
brightnessctl = lib.meta.getExe pkgs.brightnessctl;
in
[
", XF86MonBrightnessUp, exec, ${brightnessctl} -q s 5%+"
", XF86MonBrightnessDown, exec, ${brightnessctl} -q s 5%-"
];
}

View File

@@ -0,0 +1,34 @@
{
user ? throw "user argument is required",
}:
{
config,
lib,
pkgs,
...
}:
let
hmConfig = config.home-manager.users.${user.name};
in
{
home-manager.users.${user.name} = {
programs = {
btop.settings.color_theme = "matugen";
matugen.settings.templates.btop = {
input_path = ./theme.theme;
output_path = "${hmConfig.xdg.configHome}/btop/themes/matugen.theme";
};
};
theme.extraConfig = "${
lib.meta.getExe (
pkgs.writeShellApplication {
name = "reload-btop";
runtimeInputs = with pkgs; [ procps ];
text = "exec pkill btop -SIGUSR2";
}
)
} &";
};
}

View File

@@ -0,0 +1,50 @@
theme[main_bg]="{{colors.surface.default.hex}}"
theme[main_fg]="{{colors.on_surface.default.hex}}"
theme[title]="{{colors.on_surface.default.hex}}"
theme[hi_fg]="{{colors.primary.default.hex}}"
theme[selected_bg]="{{colors.primary_container.default.hex}}"
theme[selected_fg]="{{colors.on_primary_container.default.hex}}"
theme[inactive_fg]="{{colors.surface_variant.default.hex}}"
theme[graph_text]="{{colors.on_surface_variant.default.hex}}"
theme[proc_misc]="{{colors.primary.default.hex}}"
theme[cpu_box]="{{colors.outline.default.hex}}"
theme[mem_box]="{{colors.outline.default.hex}}"
theme[net_box]="{{colors.outline.default.hex}}"
theme[proc_box]="{{colors.outline.default.hex}}"
theme[div_line]="{{colors.outline_variant.default.hex}}"
theme[temp_start]="{{colors.primary.default.hex}}"
theme[temp_mid]=""
theme[temp_end]="{{colors.error.default.hex}}"
theme[cpu_start]="{{colors.primary.default.hex}}"
theme[cpu_mid]=""
theme[cpu_end]="{{colors.error.default.hex}}"
theme[used_start]="{{colors.primary.default.hex}}"
theme[used_mid]=""
theme[used_end]="{{colors.secondary.default.hex}}"
theme[available_start]="{{colors.tertiary.default.hex}}"
theme[available_mid]=""
theme[available_end]="{{colors.secondary.default.hex}}"
theme[cached_start]="{{colors.primary.default.hex}}"
theme[cached_mid]=""
theme[cached_end]="{{colors.secondary.default.hex}}"
theme[free_start]="{{colors.tertiary.default.hex}}"
theme[free_mid]=""
theme[free_end]="{{colors.secondary.default.hex}}"
theme[download_start]="{{colors.primary.default.hex}}"
theme[download_mid]=""
theme[download_end]="{{colors.secondary.default.hex}}"
theme[upload_start]="{{colors.primary.default.hex}}"
theme[upload_mid]=""
theme[upload_end]="{{colors.tertiary.default.hex}}"

View File

@@ -0,0 +1,20 @@
{
user ? throw "user argument is required",
}:
{
config,
lib,
pkgs,
...
}:
{
home-manager.users.${user.name} = {
services.cbatticon = {
enable = true;
lowLevelPercent = 20;
criticalLevelPercent = 10;
};
systemd.user.services.cbatticon.Unit.After = [ "graphical-session.target" ];
};
}

View File

@@ -0,0 +1,37 @@
{
user ? throw "user argument is required",
}:
{
config,
lib,
pkgs,
...
}:
let
hmConfig = config.home-manager.users.${user.name};
in
{
home-manager.users.${user.name} = {
home = {
packages = with pkgs; [
wl-clipboard
cliphist
];
persistence."/cache${user.home}".directories = [ "${hmConfig.xdg.relativeCacheHome}/cliphist" ];
};
services.cliphist.enable = true;
wayland.windowManager.hyprland.settings.bind =
let
cliphist = lib.meta.getExe pkgs.cliphist;
rofi = lib.meta.getExe pkgs.rofi-wayland;
wl-copy = "${pkgs.wl-clipboard}/bin/wl-copy";
in
[
"$mod, v, exec, ${cliphist} list | ${rofi} -cache-dir ${hmConfig.xdg.cacheHome}/rofi -dmenu -display-columns 2 | ${cliphist} decode | ${wl-copy}"
"$mod_CTRL, v, exec, ${cliphist} list | ${rofi} -cache-dir ${hmConfig.xdg.cacheHome}/rofi -dmenu -display-columns 2 | ${cliphist} delete"
"$mod_CTRL_SHIFT, v, exec, ${cliphist} wipe"
];
};
}

View File

@@ -0,0 +1,121 @@
{
user ? throw "user argument is required",
}:
{ lib, pkgs, ... }:
{
home-manager.users.${user.name} = {
programs.firefox = {
enable = true;
policies = {
DisableTelemetry = true;
DisableFirefoxStudies = true;
DontCheckDefaultBrowser = true;
DisablePocket = true;
DefaultDownloadDirectory = "\${HOME}/Downloads";
OfferToSaveLogins = false;
AutofillAddressEnabled = false;
AutofillCreditCardEnabled = false;
Preferences = {
"browser.aboutConfig.showWarning" = false;
"browser.contentblocking.category" = "strict";
"browser.download.useDownloadDir" = false;
"browser.newtabpage.activity-stream.feeds.section.topstories" = false;
"browser.newtabpage.activity-stream.showSponsored" = false;
"browser.newtabpage.activity-stream.showSponsoredTopSites" = false;
"browser.toolbars.bookmarks.visibility" = true;
"browser.sessionstore.restore_on_demand" = true;
"browser.sessionstore.restore_pinned_tabs_on_demand" = false;
"browser.translations.automaticallyPopup" = false;
};
};
profiles.default = {
search = {
default = "DuckDuckGo";
privateDefault = "DuckDuckGo";
order = [
"DuckDuckGo"
"Google"
"Wikipedia (en)"
"Nix Packages"
"Nix Options"
"Home Manager Options"
];
force = true;
engines = {
"Google".metaData.alias = "@g";
"DuckDuckGo".metaData.alias = "@d";
"Wikipedia (en)".metaData.alias = "@w";
"Nix Packages" = {
urls = [
{
template = "https://search.nixos.org/packages";
params = [
{
name = "type";
value = "packages";
}
{
name = "query";
value = "{searchTerms}";
}
];
}
];
icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
definedAliases = [ "@np" ];
};
"Nix Options" = {
urls = [
{
template = "https://search.nixos.org/options";
params = [
{
name = "type";
value = "options";
}
{
name = "query";
value = "{searchTerms}";
}
];
}
];
icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
definedAliases = [ "@no" ];
};
"Home Manager Options" = {
urls = [
{
template = "https://home-manager-options.extranix.com/";
params = [
{
name = "query";
value = "{searchTerms}";
}
];
}
];
icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
definedAliases = [ "@nh" ];
};
};
};
};
};
wayland.windowManager.hyprland.settings.bind = [ "$mod, b, exec, ${lib.meta.getExe pkgs.firefox}" ];
home.persistence = {
"/persist${user.home}".directories = [ ".mozilla" ];
"/cache${user.home}".directories = [ ".cache/mozilla" ];
};
};
}

View File

@@ -0,0 +1,73 @@
{
user ? throw "user argument is required",
}:
{
config,
lib,
pkgs,
...
}:
let
hmConfig = config.home-manager.users.${user.name};
in
{
home-manager.users.${user.name} = {
gtk = {
enable = true;
theme = {
package = pkgs.adw-gtk3;
name = "adw-gtk3-dark";
};
font = {
name = builtins.head hmConfig.theme.font.sansSerif.names;
package = builtins.head hmConfig.theme.font.sansSerif.packages;
inherit (hmConfig.theme.font) size;
};
iconTheme = {
name = builtins.head hmConfig.theme.icon.names;
package = builtins.head hmConfig.theme.icon.packages;
};
gtk2.configLocation = "${hmConfig.xdg.configHome}/gtk-2.0/gtkrc";
gtk3.extraCss = "@import './theme.css';";
gtk4.extraCss = "@import './theme.css';";
};
home.pointerCursor.gtk.enable = true;
programs.matugen.settings.templates = {
gtk3 = {
input_path = ./theme.css;
output_path = "${hmConfig.xdg.configHome}/gtk-3.0/theme.css";
};
gtk4 = {
input_path = ./theme.css;
output_path = "${hmConfig.xdg.configHome}/gtk-4.0/theme.css";
};
};
theme.extraConfig = "${
lib.meta.getExe (
pkgs.writeShellApplication {
name = "theme-gtk";
runtimeInputs = with pkgs; [ dconf ];
text = ''
MODE=$(cat "${hmConfig.theme.configDir}/mode")
if [ "$MODE" = "light" ]; then
GTK_THEME="adw-gtk3"
else
GTK_THEME="adw-gtk3-dark"
fi
dconf write /org/gnome/desktop/interface/gtk-theme "'$GTK_THEME'"
dconf write /org/gnome/desktop/interface/color-scheme "'prefer-$MODE'"
'';
}
)
} &";
};
}

View File

@@ -0,0 +1,48 @@
@define-color window_bg_color alpha({{colors.surface.default.hex}}, {{custom.opacity}});
@define-color window_fg_color {{colors.on_surface.default.hex}};
@define-color view_bg_color @window_bg_color;
@define-color view_fg_color @window_fg_color;
@define-color accent_bg_color {{colors.primary_container.default.hex}};
@define-color accent_fg_color {{colors.on_primary_container.default.hex}};
@define-color accent_color {{colors.primary.default.hex}};
@define-color headerbar_bg_color @window_bg_color;
@define-color headerbar_fg_color @window_fg_color;
@define-color headerbar_backdrop_color alpha({{colors.surface_variant.default.hex}}, {{custom.opacity}});
@define-color headerbar_shade_color {{colors.shadow.default.hex}};
@define-color card_bg_color alpha({{colors.surface_container.default.hex}}, {{custom.opacity}});
@define-color card_fg_color {{colors.on_surface_variant.default.hex}};
@define-color card_shade_color {{colors.shadow.default.hex}};
@define-color popover_bg_color @window_bg_color;
@define-color popover_fg_color @window_fg_color;
@define-color dialog_bg_color @window_bg_color;
@define-color dialog_fg_color @window_fg_color;
@define-color sidebar_bg_color @card_bg_color;
@define-color sidebar_fg_color @card_fg_color;
@define-color sidebar_backdrop_color alpha({{colors.surface_variant.default.hex}}, {{custom.opacity}});
@define-color sidebar_shade_color @card_shade_color;
@define-color warning_bg_color {{colors.warning_container.default.hex}};
@define-color warning_fg_color {{colors.on_warning_container.default.hex}};
@define-color warning_color {{colors.warning.default.hex}};
@define-color error_bg_color {{colors.error_container.default.hex}};
@define-color error_fg_color {{colors.on_error_container.default.hex}};
@define-color error_color {{colors.error.default.hex}};
@define-color success_bg_color {{colors.success_container.default.hex}};
@define-color success_fg_color {{colors.on_success_container.default.hex}};
@define-color success_color {{colors.success.default.hex}};
@define-color destructive_bg_color {{colors.danger_container.default.hex}};
@define-color destructive_fg_color {{colors.on_danger_container.default.hex}};
@define-color destructive_color {{colors.danger.default.hex}};
@define-color panel_bg_color @window_bg_color;
@define-color panel_fg_color @window_fg_color;

View File

@@ -0,0 +1,157 @@
{
user ? throw "user argument is required",
}:
{
config,
lib,
pkgs,
...
}:
let
hmConfig = config.home-manager.users.${user.name};
in
{
programs.hyprland.enable = true;
home-manager.users.${user.name} = {
imports = [ ./options.nix ];
wayland.windowManager.hyprland = {
enable = true;
settings = {
"$mod" = "SUPER";
"$term" = lib.meta.getExe pkgs.kitty;
bind = [
"$mod, Return, exec, $term"
"$mod, `, togglespecialworkspace"
"$mod, 1, workspace, 1"
"$mod, 2, workspace, 2"
"$mod, 3, workspace, 3"
"$mod, 4, workspace, 4"
"$mod, 5, workspace, 5"
"$mod, 6, workspace, 6"
"$mod, 7, workspace, 7"
"$mod, 8, workspace, 8"
"$mod, 9, workspace, 9"
"$mod, 0, workspace, 10"
"$mod_SHIFT, `, movetoworkspacesilent, special"
"$mod_SHIFT, 1, movetoworkspacesilent, 1"
"$mod_SHIFT, 2, movetoworkspacesilent, 2"
"$mod_SHIFT, 3, movetoworkspacesilent, 3"
"$mod_SHIFT, 4, movetoworkspacesilent, 4"
"$mod_SHIFT, 5, movetoworkspacesilent, 5"
"$mod_SHIFT, 6, movetoworkspacesilent, 6"
"$mod_SHIFT, 7, movetoworkspacesilent, 7"
"$mod_SHIFT, 8, movetoworkspacesilent, 8"
"$mod_SHIFT, 9, movetoworkspacesilent, 9"
"$mod_SHIFT, 0, movetoworkspacesilent, 10"
"$mod_CTRL, Space, workspaceopt, allfloat"
"$mod, left, movefocus, l"
"$mod, h, movefocus, l"
"$mod, down, movefocus, d"
"$mod, j, movefocus, d"
"$mod, up, movefocus, u"
"$mod, k, movefocus, u"
"$mod, right, movefocus, r"
"$mod, l, movefocus, r"
"$mod_SHIFT, left, movewindow, l"
"$mod_SHIFT, h, movewindow, l"
"$mod_SHIFT, down, movewindow, d"
"$mod_SHIFT, j, movewindow, d"
"$mod_SHIFT, up, movewindow, u"
"$mod_SHIFT, k, movewindow, u"
"$mod_SHIFT, right, movewindow, r"
"$mod_SHIFT, l, movewindow, r"
"$mod, Tab, cyclenext"
"$mod, Tab, bringactivetotop"
"$mod_SHIFT, Tab, cyclenext, prev"
"$mod_SHIFT, Tab, bringactivetotop"
"$mod, f, fullscreen, 0"
"$mod, m, fullscreen, 1"
"$mod, p, pin"
"$mod, Space, togglefloating"
"$mod, Space, centerwindow"
"$mod, q, killactive"
"CTRL_ALT, Delete, exit"
];
binde = [
"$mod_CTRL, left, resizeactive, -20 0"
"$mod_CTRL, h, resizeactive, -20 0"
"$mod_CTRL, down, resizeactive, 0 20"
"$mod_CTRL, j, resizeactive, 0 20"
"$mod_CTRL, up, resizeactive, 0 -20"
"$mod_CTRL, k, resizeactive, 0 -20"
"$mod_CTRL, right, resizeactive, 20 0"
"$mod_CTRL, l, resizeactive, 20 0"
];
bindm = [
"$mod, mouse:272, movewindow"
"$mod, mouse:273, resizewindow"
];
input = {
accel_profile = "flat";
};
gestures = {
workspace_swipe = true;
workspace_swipe_min_fingers = true;
workspace_swipe_forever = true;
workspace_swipe_cancel_ratio = 0.2;
};
misc = {
disable_hyprland_logo = true;
disable_splash_rendering = true;
new_window_takes_over_fullscreen = 2;
};
decoration.blur = {
passes = 2;
popups = true;
};
input.touchpad.natural_scroll = true;
};
extraConfig = "source = ./theme.conf";
};
programs = {
zsh.loginExtra = lib.mkAfter ''
if [ -z "$WAYLAND_DISPLAY" ] && [ -n "$XDG_VTNR" ] && [ "$XDG_VTNR" -eq 1 ]; then
hyprland &> /tmp/hyprland.log
fi
'';
matugen.settings.templates.hyprland = {
input_path = ./theme.conf;
output_path = "${hmConfig.xdg.configHome}/hypr/theme.conf";
};
};
theme.extraConfig = "${
lib.meta.getExe (
pkgs.writeShellApplication {
name = "reload-hyprland";
runtimeInputs = with pkgs; [ hyprland ];
text = "exec hyprctl reload";
}
)
} &";
home.sessionVariables.NIXOS_OZONE_WL = "1";
};
}

View File

@@ -0,0 +1,43 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.wayland.windowManager.hyprland;
in
{
options.wayland.windowManager.hyprland =
with lib;
with types;
{
initExtraConfig = mkOption {
type = lines;
default = "";
description = "Extra configuration lines to add to exec-once";
};
reloadExtraConfig = mkOption {
type = lines;
default = "";
description = "Extra configuration lines to add to exec";
};
};
config = {
wayland.windowManager.hyprland.settings.exec-once = lib.meta.getExe (
pkgs.writeShellApplication {
name = "init-hyprland";
text = cfg.initExtraConfig;
}
);
wayland.windowManager.hyprland.settings.exec = lib.meta.getExe (
pkgs.writeShellApplication {
name = "reload-hyprland";
text = cfg.reloadExtraConfig;
}
);
};
}

View File

@@ -0,0 +1,22 @@
general {
gaps_in = {{custom.padding}}
gaps_out = {{custom.padding_double}}
col.inactive_border = rgba({{colors.surface.default.hex_stripped}}{{custom.opacity_hex | to_lower}})
col.active_border = rgb({{colors.primary.default.hex_stripped}})
}
decoration {
rounding = {{custom.radius}}
col.shadow = rgba({{colors.shadow.default.hex_stripped}}{{custom.opacity_shadow_hex | to_lower}})
blur {
size = {{custom.blur}}
}
}
misc {
col.splash = rgb({{colors.on_surface.default.hex_stripped}})
background_color = rgb({{colors.surface.default.hex_stripped}})
font_family = {{custom.font_sans_serif}}
splash_font_family = {{custom.font_monospace}}
}

View File

@@ -0,0 +1,44 @@
{
user ? throw "user argument is required",
}:
{
config,
lib,
pkgs,
...
}:
let
hmConfig = config.home-manager.users.${user.name};
in
{
home-manager.users.${user.name} = {
home = {
packages = with pkgs; [
hyprshot
swappy
];
sessionVariables.HYPRSHOT_DIR = "${hmConfig.xdg.userDirs.pictures}/screenshots";
};
wayland.windowManager.hyprland.settings.bind =
let
hyprshot = lib.meta.getExe pkgs.hyprshot;
date = "${pkgs.coreutils}/bin/date";
filename = "\"$(${date} +'%Y-%m-%d-%H%M%S.png')\"";
swappyWrapper = lib.meta.getExe (
pkgs.writeShellApplication {
name = "swappy-wrapper";
runtimeInputs = with pkgs; [ swappy ];
text = "exec swappy -f \"$1\"";
}
);
in
[
", Print, exec, ${hyprshot} -m output -m active -f ${filename}"
"SHIFT, Print, exec, ${hyprshot} -m output -m active -f ${filename} -- ${swappyWrapper}"
", XF86SelectiveScreenshot, exec, ${hyprshot} -m region -z -f ${filename}"
"SHIFT, XF86SelectiveScreenshot, exec, ${hyprshot} -m region -z -f ${filename} -- ${swappyWrapper}"
];
};
}

View File

@@ -0,0 +1,49 @@
{
user ? throw "user argument is required",
}:
{
config,
lib,
pkgs,
...
}:
let
hmConfig = config.home-manager.users.${user.name};
in
{
home-manager.users.${user.name} = {
programs = {
kitty = {
enable = true;
font = {
name = builtins.head hmConfig.theme.font.monospace.names;
package = builtins.head hmConfig.theme.font.monospace.packages;
inherit (hmConfig.theme.font) size;
};
extraConfig = ''
confirm_os_window_close 0
include theme.conf
'';
};
matugen.settings.templates.kitty = {
input_path = ./theme.conf;
output_path = "${hmConfig.xdg.configHome}/kitty/theme.conf";
};
};
theme.extraConfig = "${
lib.meta.getExe (
pkgs.writeShellApplication {
name = "reload-kitty";
runtimeInputs = with pkgs; [ procps ];
text = "exec pkill kitty -SIGUSR1";
}
)
} &";
home.persistence."/cache${user.home}".directories = [ "${hmConfig.xdg.relativeCacheHome}/kitty" ];
};
}

View File

@@ -0,0 +1,29 @@
background_tint 0.0
background_opacity {{custom.opacity}}
background {{colors.surface.default.hex}}
foreground {{colors.on_surface.default.hex}}
selection_background {{colors.primary.default.hex}}
selection_foreground {{colors.on_primary.default.hex}}
url_color {{colors.tertiary.default.hex}}
cursor {{colors.on_surface.default.hex}}
color0 {{colors.surface.default.hex}}
color1 {{colors.red.default.hex}}
color2 {{colors.green.default.hex}}
color3 {{colors.yellow.default.hex}}
color4 {{colors.blue.default.hex}}
color5 {{colors.magenta.default.hex}}
color6 {{colors.cyan.default.hex}}
color7 {{colors.on_surface.default.hex}}
color8 {{colors.outline_variant.default.hex}}
color9 {{ colors.red.default.hex | set_lightness: 5.0 }}
color10 {{ colors.green.default.hex | set_lightness: 5.0 }}
color11 {{ colors.yellow.default.hex | set_lightness: 5.0 }}
color12 {{ colors.blue.default.hex | set_lightness: 5.0 }}
color13 {{ colors.magenta.default.hex | set_lightness: 5.0 }}
color14 {{ colors.cyan.default.hex | set_lightness: 5.0 }}
color15 {{colors.on_surface_variant.default.hex}}

View File

@@ -0,0 +1,99 @@
{
user ? throw "user argument is required",
}:
{
config,
lib,
pkgs,
...
}:
let
hmConfig = config.home-manager.users.${user.name};
in
{
home-manager.users.${user.name} = {
imports = [ ./options.nix ];
programs.matugen = {
enable = true;
settings = {
config = {
custom_colors =
let
mkColor = category: color: {
color = hmConfig.theme.color.${category}.${color};
blend = hmConfig.theme.color.${category}.blend;
};
in
{
danger = mkColor "semantic" "danger";
warning = mkColor "semantic" "warning";
success = mkColor "semantic" "success";
info = mkColor "semantic" "info";
red = mkColor "ansi" "red";
green = mkColor "ansi" "green";
yellow = mkColor "ansi" "yellow";
orange = mkColor "ansi" "orange";
blue = mkColor "ansi" "blue";
magenta = mkColor "ansi" "magenta";
cyan = mkColor "ansi" "cyan";
keywords = mkColor "syntax" "keywords";
functions = mkColor "syntax" "functions";
properties = mkColor "syntax" "properties";
constants = mkColor "syntax" "constants";
strings = mkColor "syntax" "strings";
numbers = mkColor "syntax" "numbers";
structures = mkColor "syntax" "structures";
types = mkColor "syntax" "types";
};
custom_keywords =
let
zeroPad = hex: if builtins.stringLength hex == 1 then "0${hex}" else hex;
percentageToHex = percentage: zeroPad (lib.trivial.toHexString (builtins.floor (percentage * 255)));
in
{
flavour = hmConfig.theme.flavour;
contrast = builtins.toString hmConfig.theme.contrast;
radius = builtins.toString hmConfig.theme.radius;
padding = builtins.toString hmConfig.theme.padding;
padding_double = builtins.toString (hmConfig.theme.padding * 2);
blur = builtins.toString hmConfig.theme.blur;
opacity = builtins.toString hmConfig.theme.opacity;
opacity_hex = builtins.toString (percentageToHex hmConfig.theme.opacity);
opacity_shadow = builtins.toString (hmConfig.theme.opacity * 0.75);
opacity_shadow_hex = builtins.toString (percentageToHex (hmConfig.theme.opacity * 0.75));
font_size = builtins.toString hmConfig.theme.font.size;
font_sans_serif = builtins.head hmConfig.theme.font.sansSerif.names;
font_sans_serif_all = builtins.concatStringsSep ", " hmConfig.theme.font.sansSerif.names;
font_serif = builtins.head hmConfig.theme.font.serif.names;
font_serif_all = builtins.concatStringsSep ", " hmConfig.theme.font.serif.names;
font_monospace = builtins.head hmConfig.theme.font.monospace.names;
font_monospace_all = builtins.concatStringsSep ", " hmConfig.theme.font.monospace.names;
font_emoji = builtins.head hmConfig.theme.font.emoji.names;
font_emoji_all = builtins.concatStringsSep ", " hmConfig.theme.font.emoji.names;
};
};
templates = { };
};
};
theme.extraConfig = lib.mkBefore (
lib.meta.getExe (
pkgs.writeShellApplication {
name = "theme-matugen";
runtimeInputs = with pkgs; [ matugen ];
text = ''
exec matugen image "${hmConfig.theme.configDir}/wallpaper" \
--type scheme-${hmConfig.theme.flavour} \
--mode "$(cat "${hmConfig.theme.configDir}/mode")" \
--contrast ${builtins.toString hmConfig.theme.contrast}
'';
}
)
);
};
}

View File

@@ -0,0 +1,30 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.programs.matugen;
in
{
# https://github.com/Theaninova/matugen/blob/add-home-manager-module/hm-module.nix
options.programs.matugen =
with lib;
with types;
{
enable = mkEnableOption "matugen";
package = mkPackageOption pkgs "matugen" { };
settings = mkOption {
type = attrsOf anything;
description = "Settings to write to config.toml.";
};
};
config = lib.mkIf cfg.enable {
home.packages = [ cfg.package ];
xdg.configFile."matugen/config.toml".source = lib.mkIf (cfg.settings != null) (
(pkgs.formats.toml { }).generate "matugen" cfg.settings
);
};
}

View File

@@ -0,0 +1,10 @@
{
user ? throw "user argument is required",
}:
{ ... }:
{
home-manager.users.${user.name} = {
services.network-manager-applet.enable = true;
systemd.user.services.network-manager-applet.Unit.After = [ "graphical-session.target" ];
};
}

View File

@@ -0,0 +1,34 @@
{
user ? throw "user argument is required",
}:
{ lib, pkgs, ... }:
{
home-manager.users.${user.name} = {
home.packages = with pkgs; [ pavucontrol ];
wayland.windowManager.hyprland.settings =
let
wpctl = "${pkgs.wireplumber}/bin/wpctl";
playerctl = lib.meta.getExe pkgs.playerctl;
in
{
bindle = [
", XF86AudioRaiseVolume, exec, ${wpctl} set-volume @DEFAULT_AUDIO_SINK@ -l 2.0 2%+"
", XF86AudioLowerVolume, exec, ${wpctl} set-volume @DEFAULT_AUDIO_SINK@ -l 2.0 2%-"
"CTRL, XF86AudioRaiseVolume, exec, ${wpctl} set-volume @DEFAULT_AUDIO_SOURCE@ -l 1.0 2%+"
"CTRL, XF86AudioLowerVolume, exec, ${wpctl} set-volume @DEFAULT_AUDIO_SOURCE@ -l 1.0 2%-"
", XF86AudioNext, exec, ${playerctl} next"
", XF86AudioPrev, exec, ${playerctl} previous"
"CTRL, XF86AudioNext, exec, ${playerctl} position 10+"
"CTRL, XF86AudioPrev, exec, ${playerctl} position 10-"
];
bindl = [
", XF86AudioMute, exec, ${wpctl} set-mute @DEFAULT_AUDIO_SINK@ toggle"
", XF86AudioMicMute, exec, ${wpctl} set-mute @DEFAULT_AUDIO_SOURCE@ toggle"
", XF86AudioPlay, exec, ${playerctl} play-pause"
", XF86AudioStop, exec, ${playerctl} stop"
];
};
};
}

View File

@@ -0,0 +1,50 @@
{
user ? throw "user argument is required",
}:
{
lib,
config,
pkgs,
...
}:
let
hmConfig = config.home-manager.users.${user.name};
qalculate-gtk = pkgs.qalculate-gtk.overrideAttrs (oldAttrs: {
patches = oldAttrs.patches or [ ] ++ [ ./skip-save-prefs.patch ];
});
in
{
home-manager.users.${user.name} = {
home = {
packages = [ qalculate-gtk ];
persistence."/cache${user.home}".files = [
"${hmConfig.xdg.relativeConfigHome}/qalculate/qalculate-gtk.history"
];
};
xdg.configFile."qalculate/qalculate-gtk.cfg".source =
(pkgs.formats.ini { }).generate "qalculate-gtk.cfg"
{
General = {
allow_multiple_instances = 1;
width = 500;
save_history_separately = 1;
auto_update_exchange_rates = 1;
local_currency_conversion = 1;
use_binary_prefixes = 1;
persistent_keypad = 1;
copy_ascii = 1;
copy_ascii_without_units = 1;
};
Mode = {
calculate_as_you_type = 1;
excessive_parenthesis = 1;
};
};
wayland.windowManager.hyprland.settings = {
bind = [ ", XF86Calculator, exec, ${lib.meta.getExe qalculate-gtk}" ];
windowrulev2 = [ "float, class:(qalculate-gtk)" ];
};
};
}

View File

@@ -0,0 +1,12 @@
diff --git a/src/callbacks.cc b/src/callbacks.cc
index 14ab38a..5f73451 100644
--- a/src/callbacks.cc
+++ b/src/callbacks.cc
@@ -23405,6 +23405,7 @@ bool save_history(bool allow_cancel) {
*/
bool save_preferences(bool mode, bool allow_cancel) {
+ return true;
FILE *file = NULL;
string homedir = getLocalDir();

View File

@@ -0,0 +1,566 @@
[%General]
x11drag=menubar_and_primary_toolbar
alt_mnemonic=true
left_tabs=false
attach_active_tab=false
mirror_doc_tabs=false
group_toolbar_buttons=true
toolbar_item_spacing=0
toolbar_interior_spacing=2
spread_progressbar=true
composite=true
menu_shadow_depth=16
spread_menuitems=true
tooltip_shadow_depth=7
splitter_width=1
scroll_width=9
scroll_arrows=false
scroll_min_extent=60
slider_width=2
slider_handle_width=23
slider_handle_length=22
tickless_slider_handle_size=22
center_toolbar_handle=true
check_size=24
textless_progressbar=false
progressbar_thickness=2
menubar_mouse_tracking=true
toolbutton_style=1
double_click=false
translucent_windows=false
blurring=false
popup_blurring=false
vertical_spin_indicators=false
spin_button_width=24
fill_rubberband=false
merge_menubar_with_toolbar=true
small_icon_size=16
large_icon_size=32
button_icon_size=16
toolbar_icon_size=16
combo_as_lineedit=true
animate_states=true
button_contents_shift=false
combo_menu=true
hide_combo_checkboxes=true
combo_focus_rect=false
groupbox_top_label=true
inline_spin_indicators=true
joined_inactive_tabs=false
layout_spacing=6
layout_margin=9
scrollbar_in_view=true
transient_scrollbar=true
transient_groove=true
submenu_overlap=0
tooltip_delay=0
tree_branch_line=true
no_window_pattern=false
opaque=vlc
reduce_window_opacity=0
respect_DE=true
scrollable_menu=false
submenu_delay=150
no_inactiveness=false
reduce_menu_opacity=0
click_behavior=0
contrast=1.00
dialog_button_layout=0
intensity=1.00
saturation=1.00
shadowless_popup=false
drag_from_buttons=false
menu_blur_radius=0
tooltip_blur_radius=0
[GeneralColors]
window.color={{colors.surface.default.hex}}
base.color={{colors.surface.default.hex}}
alt.base.color={{colors.surface_container.default.hex}}
button.color={{colors.surface_container_highest.default.hex}}
light.color={{colors.surface_container_highest.default.hex}}
mid.light.color={{colors.surface_container_high.default.hex}}
dark.color={{colors.surface_container_low.default.hex}}
mid.color={{colors.surface_container.default.hex}}
highlight.color={{colors.primary.default.hex}}
inactive.highlight.color={{colors.primary.default.hex}}
text.color={{colors.on_surface.default.hex}}
window.text.color={{colors.on_surface.default.hex}}
button.text.color={{colors.on_surface.default.hex}}
disabled.text.color={{colors.outline.default.hex}}
tooltip.text.color={{colors.on_surface.default.hex}}
highlight.text.color={{colors.on_surface.default.hex}}
link.color={{colors.primary.default.hex}}
link.visited.color={{colors.secondary.default.hex}}
progress.indicator.text.color={{colors.on_surface.default.hex}}
[Hacks]
transparent_ktitle_label=true
transparent_dolphin_view=true
transparent_pcmanfm_sidepane=true
blur_translucent=false
transparent_menutitle=true
respect_darkness=true
kcapacitybar_as_progressbar=true
force_size_grip=true
iconless_pushbutton=true
iconless_menu=false
disabled_icon_opacity=100
lxqtmainmenu_iconsize=16
normal_default_pushbutton=true
single_top_toolbar=true
tint_on_mouseover=0
transparent_pcmanfm_view=true
no_selection_tint=true
transparent_arrow_button=true
middle_click_scroll=false
opaque_colors=false
kinetic_scrolling=false
scroll_jump_workaround=true
centered_forms=false
noninteger_translucency=false
style_vertical_toolbars=false
blur_only_active_window=true
[PanelButtonCommand]
frame=true
frame.element=button
frame.top=6
frame.bottom=6
frame.left=6
frame.right=6
interior=true
interior.element=button
indicator.size=8
text.normal.color={{colors.on_surface.default.hex}}
text.focus.color={{colors.on_surface.default.hex}}
text.press.color={{colors.on_surface.default.hex}}
text.toggle.color={{colors.on_surface.default.hex}}
text.shadow=0
text.margin=4
text.iconspacing=4
indicator.element=arrow
frame.expansion=0
[PanelButtonTool]
inherits=PanelButtonCommand
text.normal.color={{colors.on_surface.default.hex}}
text.focus.color={{colors.on_surface.default.hex}}
text.press.color={{colors.on_surface.default.hex}}
text.toggle.color={{colors.on_surface.default.hex}}
text.bold=false
indicator.element=arrow
indicator.size=0
frame.expansion=0
[ToolbarButton]
frame=true
frame.element=tbutton
interior.element=tbutton
frame.top=16
frame.bottom=16
frame.left=16
frame.right=16
indicator.element=tarrow
text.normal.color={{colors.on_surface.default.hex}}
text.focus.color={{colors.on_surface.default.hex}}
text.press.color={{colors.on_surface.default.hex}}
text.toggle.color={{colors.on_surface.default.hex}}
text.bold=false
frame.expansion=32
[Dock]
inherits=PanelButtonCommand
interior.element=dock
frame.element=dock
frame.top=1
frame.bottom=1
frame.left=1
frame.right=1
text.normal.color={{colors.on_surface.default.hex}}
[DockTitle]
inherits=PanelButtonCommand
frame=false
interior=false
text.normal.color={{colors.on_surface.default.hex}}
text.focus.color={{colors.on_surface.default.hex}}
text.bold=false
[IndicatorSpinBox]
inherits=PanelButtonCommand
frame=true
interior=true
frame.top=2
frame.bottom=2
frame.left=2
frame.right=2
indicator.element=spin
indicator.size=8
text.normal.color={{colors.on_surface.default.hex}}
text.margin.top=2
text.margin.bottom=2
text.margin.left=2
text.margin.right=2
[RadioButton]
inherits=PanelButtonCommand
frame=false
interior.element=radio
text.normal.color={{colors.on_surface.default.hex}}
text.focus.color={{colors.on_surface.default.hex}}
min_width=+0.3font
min_height=+0.3font
[CheckBox]
inherits=PanelButtonCommand
frame=false
interior.element=checkbox
text.normal.color={{colors.on_surface.default.hex}}
text.focus.color={{colors.on_surface.default.hex}}
min_width=+0.3font
min_height=+0.3font
[Focus]
inherits=PanelButtonCommand
frame=true
frame.element=focus
frame.top=2
frame.bottom=2
frame.left=2
frame.right=2
frame.patternsize=14
[GenericFrame]
inherits=PanelButtonCommand
frame=true
interior=false
frame.element=common
interior.element=common
frame.top=1
frame.bottom=1
frame.left=1
frame.right=1
[LineEdit]
inherits=PanelButtonCommand
frame.element=lineedit
interior.element=lineedit
frame.top=6
frame.bottom=6
frame.left=6
frame.right=6
text.margin.top=2
text.margin.bottom=2
text.margin.left=2
text.margin.right=2
[ToolbarLineEdit]
frame.element=lineedit
interior.element=lineedit
[DropDownButton]
inherits=PanelButtonCommand
indicator.element=arrow-down
[IndicatorArrow]
indicator.element=arrow
indicator.size=8
[ToolboxTab]
inherits=PanelButtonCommand
text.normal.color={{colors.on_surface.default.hex}}
text.press.color={{colors.on_surface.default.hex}}
text.focus.color={{colors.on_surface.default.hex}}
[Tab]
inherits=PanelButtonCommand
interior.element=tab
text.margin.left=8
text.margin.right=8
text.margin.top=0
text.margin.bottom=0
frame.element=tab
indicator.element=tab
indicator.size=22
frame.top=8
frame.bottom=8
frame.left=8
frame.right=8
text.normal.color={{colors.on_surface.default.hex}}
text.focus.color={{colors.on_surface.default.hex}}
text.press.color={{colors.on_surface.default.hex}}
text.toggle.color={{colors.on_surface.default.hex}}
frame.expansion=0
text.bold=false
[TabFrame]
inherits=PanelButtonCommand
frame.element=tabframe
interior.element=tabframe
frame.top=24
frame.bottom=24
frame.left=24
frame.right=24
[TreeExpander]
inherits=PanelButtonCommand
indicator.size=8
indicator.element=tree
[HeaderSection]
inherits=PanelButtonCommand
interior.element=header
frame.element=header
frame.top=0
frame.bottom=1
frame.left=1
frame.right=1
text.normal.color={{colors.on_surface.default.hex}}
text.focus.color={{colors.on_surface.default.hex}}
text.press.color={{colors.on_surface.default.hex}}
text.toggle.color={{colors.on_surface.default.hex}}
frame.expansion=0
[SizeGrip]
indicator.element=resize-grip
[Toolbar]
inherits=PanelButtonCommand
indicator.element=toolbar
indicator.size=5
text.margin=0
interior.element=menubar
frame.element=menubar
text.normal.color={{colors.on_surface.default.hex}}
text.focus.color={{colors.on_surface.default.hex}}
text.press.color={{colors.on_surface.default.hex}}
text.toggle.color={{colors.on_surface.default.hex}}
frame.left=6
frame.right=6
frame.top=0
frame.bottom=1
frame.expansion=0
[Slider]
inherits=PanelButtonCommand
frame.element=slider
focusFrame=true
interior.element=slider
frame.top=3
frame.bottom=3
frame.left=3
frame.right=3
[SliderCursor]
inherits=PanelButtonCommand
frame=false
interior.element=slidercursor
[Progressbar]
inherits=PanelButtonCommand
frame.element=progress
interior.element=progress
text.margin=0
text.normal.color={{colors.on_surface.default.hex}}
text.focus.color={{colors.on_surface.default.hex}}
text.press.color={{colors.on_surface.default.hex}}
text.toggle.color={{colors.on_surface.default.hex}}
text.bold=false
frame.expansion=8
[ProgressbarContents]
inherits=PanelButtonCommand
frame=true
frame.element=progress-pattern
interior.element=progress-pattern
[ItemView]
inherits=PanelButtonCommand
text.margin=0
frame.element=itemview
interior.element=itemview
frame.top=4
frame.bottom=4
frame.left=4
frame.right=4
text.margin.top=0
text.margin.bottom=0
text.margin.left=8
text.margin.right=8
text.normal.color={{colors.on_surface.default.hex}}
text.focus.color={{colors.on_surface.default.hex}}
text.press.color={{colors.on_surface.default.hex}}
text.toggle.color={{colors.on_surface.default.hex}}
min_width=+0.3font
min_height=+0.3font
frame.expansion=0
[Splitter]
interior.element=splitter
frame=false
indicator.size=0
[Scrollbar]
inherits=PanelButtonCommand
indicator.element=arrow
indicator.size=12
[ScrollbarSlider]
inherits=PanelButtonCommand
frame.element=scrollbarslider
interior=false
frame.left=5
frame.right=5
frame.top=5
frame.bottom=5
indicator.element=grip
indicator.size=12
[ScrollbarGroove]
inherits=PanelButtonCommand
interior=false
frame=false
[Menu]
inherits=PanelButtonCommand
frame.top=8
frame.bottom=8
frame.left=8
frame.right=8
frame.element=menu
interior.element=menu
text.normal.color={{colors.on_surface.default.hex}}
text.shadow=false
text.bold=false
[MenuItem]
inherits=PanelButtonCommand
frame=true
frame.element=menuitem
interior.element=menuitem
indicator.element=menuitem
text.normal.color={{colors.on_surface.default.hex}}
text.focus.color={{colors.on_surface.default.hex}}
text.margin.top=0
text.margin.bottom=0
text.margin.left=6
text.margin.right=6
frame.top=4
frame.bottom=4
frame.left=12
frame.right=12
text.bold=false
frame.expansion=0
[MenuBar]
inherits=PanelButtonCommand
frame.element=menubar
interior.element=menubar
frame.bottom=0
text.normal.color={{colors.on_surface.default.hex}}
text.focus.color={{colors.on_surface.default.hex}}
text.press.color={{colors.on_surface.default.hex}}
text.toggle.color={{colors.on_surface.default.hex}}
frame.expansion=0
text.bold=false
[MenuBarItem]
inherits=PanelButtonCommand
interior=true
interior.element=menubaritem
frame.element=menubaritem
frame.top=2
frame.bottom=2
frame.left=2
frame.right=2
text.margin.left=4
text.margin.right=4
text.margin.top=0
text.margin.bottom=0
text.normal.color={{colors.on_surface.default.hex}}
text.focus.color={{colors.on_surface.default.hex}}
text.press.color={{colors.on_surface.default.hex}}
text.toggle.color={{colors.on_surface.default.hex}}
text.bold=false
min_width=+0.3font
min_height=+0.3font
frame.expansion=0
[TitleBar]
inherits=PanelButtonCommand
frame=false
text.margin.top=2
text.margin.bottom=2
text.margin.left=2
text.margin.right=2
interior.element=titlebar
indicator.size=16
indicator.element=mdi
text.normal.color={{colors.on_surface.default.hex}}
text.focus.color={{colors.on_surface.default.hex}}
text.bold=false
text.italic=true
frame.expansion=0
[ComboBox]
inherits=PanelButtonCommand
frame.element=combo
interior.element=combo
frame.top=6
frame.bottom=6
frame.left=6
frame.right=6
text.margin.top=2
text.margin.bottom=2
text.margin.left=2
text.margin.right=2
text.focus.color={{colors.on_surface.default.hex}}
text.press.color={{colors.on_surface.default.hex}}
text.toggle.color={{colors.on_surface.default.hex}}
[GroupBox]
inherits=GenericFrame
frame=false
text.shadow=0
text.margin=0
text.normal.color={{colors.on_surface.default.hex}}
text.focus.color={{colors.on_surface.default.hex}}
text.bold=false
frame.expansion=0
[TabBarFrame]
inherits=GenericFrame
frame=false
frame.element=tabBarFrame
interior=false
frame.top=0
frame.bottom=0
frame.left=0
frame.right=0
[ToolTip]
inherits=GenericFrame
frame.top=6
frame.bottom=6
frame.left=6
frame.right=6
interior=true
text.shadow=0
text.margin=6
interior.element=tooltip
frame.element=tooltip
frame.expansion=6
[StatusBar]
inherits=GenericFrame
frame=false
interior=false
[Window]
interior=true
interior.element=window
frame=true
frame.element=window
frame.bottom=10
frame.top=10

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 216 KiB

View File

@@ -0,0 +1,54 @@
{
user ? throw "user argument is required",
}:
{
config,
lib,
pkgs,
...
}:
let
hmConfig = config.home-manager.users.${user.name};
in
{
home-manager.users.${user.name} = {
qt = {
enable = true;
platformTheme.name = "qtct";
style.package = with pkgs; [
libsForQt5.qtstyleplugin-kvantum
qt6Packages.qtstyleplugin-kvantum
];
};
home.sessionVariables = {
QT_QPA_PLATFORM = "wayland";
QT_QPA_PLATFORMTHEME = "qt5ct";
};
programs.matugen.settings.templates = {
# https://github.com/GabePoel/KvLibadwaita/blob/main/src/KvLibadwaita/KvLibadwaita.kvconfig
kvantumConfig = {
input_path = ./KvAdwQt/KvAdwQt.kvconfig;
output_path = "${hmConfig.xdg.configHome}/Kvantum/KvAdwQt/KvAdwQt.kvconfig";
};
# https://github.com/GabePoel/KvLibadwaita/blob/main/src/KvLibadwaita/KvLibadwaita.svg
kvantumSvg = {
input_path = ./KvAdwQt/KvAdwQt.svg;
output_path = "${hmConfig.xdg.configHome}/Kvantum/KvAdwQt/KvAdwQt.svg";
};
};
xdg.configFile =
let
qtConfig = (pkgs.formats.ini { }).generate "qt5ct.conf" { Appearance.style = "kvantum"; };
in
{
"qt5ct/qt5ct.conf".source = qtConfig;
"qt6ct/qt6ct.conf".source = qtConfig;
"Kvantum/kvantum.kvconfig".source = (pkgs.formats.ini { }).generate "kvantum.kvconfig" {
General.theme = "KvAdwQt";
};
};
};
}

View File

@@ -0,0 +1,27 @@
{
user ? throw "user argument is required",
}:
{
config,
lib,
pkgs,
...
}:
let
hmConfig = config.home-manager.users.${user.name};
in
{
home-manager.users.${user.name} = {
programs.rofi = {
enable = true;
package = pkgs.rofi-wayland;
font = builtins.head hmConfig.theme.font.monospace.names;
};
home.persistence."/cache${user.home}".directories = [ "${hmConfig.xdg.relativeCacheHome}/rofi" ];
wayland.windowManager.hyprland.settings.bind = [
"$mod, r, exec, ${lib.meta.getExe pkgs.rofi-wayland} -cache-dir ${hmConfig.xdg.cacheHome}/rofi -show drun"
];
};
}

View File

@@ -0,0 +1,64 @@
{
user ? throw "user argument is required",
}:
{
config,
lib,
pkgs,
...
}:
let
hmConfig = config.home-manager.users.${user.name};
themeSwww = lib.meta.getExe (
pkgs.writeShellApplication {
name = "theme-swww";
runtimeInputs = with pkgs; [
coreutils
swww
];
text = "exec swww img \"${hmConfig.theme.configDir}/wallpaper\"";
}
);
in
{
home-manager.users.${user.name} = {
home = {
packages = with pkgs; [ swww ];
persistence."/cache${user.home}".directories = [ "${hmConfig.xdg.relativeCacheHome}/swww" ];
};
systemd.user.services.swww = {
Unit = {
Description = "Wallpaper daemon";
BindsTo = [ "graphical-session.target" ];
After = [ "graphical-session.target" ];
};
Service = {
Type = "forking";
ExecStart = lib.meta.getExe (
pkgs.writeShellApplication {
name = "init-swww";
runtimeInputs = with pkgs; [ swww ];
text = "exec swww init";
}
);
ExecStartPost = themeSwww;
ExecStop = lib.meta.getExe (
pkgs.writeShellApplication {
name = "kill-swww";
runtimeInputs = with pkgs; [ swww ];
text = "exec swww kill";
}
);
};
Install.WantedBy = [ "graphical-session.target" ];
};
theme.extraConfig = lib.mkAfter "${themeSwww} &";
};
}

View File

@@ -0,0 +1,33 @@
{
user ? throw "user argument is required",
}:
{
config,
inputs,
lib,
pkgs,
...
}:
let
hmConfig = config.home-manager.users.${user.name};
themeBin = lib.meta.getExe hmConfig.theme.pkg;
in
{
home-manager.users.${user.name} = {
imports = [ ./options.nix ];
theme.enable = true;
wayland.windowManager.hyprland.settings.bind = [
"CTRL_ALT, r, exec, ${themeBin}"
"CTRL_ALT, t, exec, ${themeBin} toggle"
];
home = {
activation.themeInit = inputs.home-manager.lib.hm.dag.entryAfter [
"writeBoundary"
] "run ${themeBin}";
persistence."/persist${user.home}".directories = [ "${hmConfig.xdg.relativeConfigHome}/theme" ];
};
};
}

View File

@@ -0,0 +1,387 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.theme;
init = pkgs.writeShellApplication {
name = "theme";
runtimeInputs = with pkgs; [ coreutils ];
bashOptions = [
"nounset"
"pipefail"
];
runtimeEnv = {
CONFIG = cfg.configDir;
DEFAULT_WALLPAPER = cfg.wallpaper;
DEFAULT_MODE = cfg.mode;
SWITCH = lib.meta.getExe (pkgs.writeShellScriptBin "themeExtraConfig" cfg.extraConfig);
};
text = builtins.readFile ./theme.sh;
};
in
{
# https://github.com/Theaninova/TheaninovOS/blob/master/modules/home-manager/theme/md3-evo.nix
options.theme =
with lib;
with types;
{
enable = mkEnableOption "theme";
configDir = mkOption {
type = str;
default = "${config.xdg.configHome}/theme";
description = "The path to the theme config directory.";
};
wallpaper = mkOption {
type = path;
description = "The path to the default wallpaper";
};
pkg = mkOption {
type = package;
default = init;
readOnly = true;
description = "The package containing the `theme` script";
};
extraConfig = mkOption {
type = lines;
default = "";
description = "Extra configuration lines to add to the theme script.";
};
flavour = mkOption {
type = enum [
"content"
"expressive"
"fidelity"
"fruit-salad"
"monochrome"
"neutral"
"rainbow"
"tonal-spot"
];
default = "tonal-spot";
description = "The flavour of the theme.";
};
mode = mkOption {
type = enum [
"dark"
"light"
];
default = "dark";
description = "The default mode of the theme.";
};
contrast = mkOption {
type = numbers.between (-1) 1;
default = 0;
description = "Use a modified contrast.";
};
opacity = mkOption {
type = numbers.between 0 1;
default = 1;
description = "The opacity of apps.";
};
radius = mkOption {
type = ints.unsigned;
default = 8;
description = "The radius of corners.";
};
padding = mkOption {
type = ints.unsigned;
default = 8;
description = "The padding of windows.";
};
blur = mkOption {
type = ints.unsigned;
default = 0;
description = "The blur amount of windows.";
};
color = {
semantic = {
blend = mkOption {
type = bool;
default = false;
description = "Blend the colors.";
};
danger = mkOption {
type = str;
default = "#ff0000";
description = "The color of danger.";
};
warning = mkOption {
type = str;
default = "#ffff00";
description = "The color of warning.";
};
success = mkOption {
type = str;
default = "#00ff00";
description = "The color of success.";
};
info = mkOption {
type = str;
default = "#0000ff";
description = "The color of info.";
};
};
syntax = {
blend = mkOption {
type = bool;
default = true;
description = "Blend the colors.";
};
keywords = mkOption {
type = str;
default = "#ff8000";
description = "The color of keywords.";
};
functions = mkOption {
type = str;
default = "#0000ff";
description = "The color of functions.";
};
properties = mkOption {
type = str;
default = "#ff00ff";
description = "The color of properties.";
};
constants = mkOption {
type = str;
default = "#ff00ff";
description = "The color of constants.";
};
strings = mkOption {
type = str;
default = "#00ff00";
description = "The color of variables.";
};
numbers = mkOption {
type = str;
default = "#00ffff";
description = "The color of numbers.";
};
structures = mkOption {
type = str;
default = "#ffff00";
description = "The color of structures.";
};
types = mkOption {
type = str;
default = "#00ffff";
description = "The color of types.";
};
};
ansi = {
blend = mkOption {
type = bool;
default = true;
description = "Blend the colors.";
};
red = mkOption {
type = str;
default = "#ff0000";
description = "The color of red.";
};
green = mkOption {
type = str;
default = "#00ff00";
description = "The color of green.";
};
yellow = mkOption {
type = str;
default = "#ffff00";
description = "The color of yellow.";
};
orange = mkOption {
type = str;
default = "#ff8000";
description = "The color of orange.";
};
blue = mkOption {
type = str;
default = "#0000ff";
description = "The color of blue.";
};
magenta = mkOption {
type = str;
default = "#ff00ff";
description = "The color of magenta.";
};
cyan = mkOption {
type = str;
default = "#00ffff";
description = "The color of cyan.";
};
};
};
font = {
sansSerif = {
names = mkOption {
type = listOf str;
default = [ "Roboto" ];
description = "The sans serif font families.";
};
packages = mkOption {
type = listOf package;
default = with pkgs; [ roboto ];
description = "The sans serif font packages.";
};
};
serif = {
names = mkOption {
type = listOf str;
default = [ "Roboto Serif" ];
description = "The serif font families.";
};
packages = mkOption {
type = listOf package;
default = with pkgs; [ roboto-serif ];
description = "The serif font packages.";
};
};
monospace = {
names = mkOption {
type = listOf str;
default = [ "JetBrainsMono Nerd Font" ];
description = "The monospace font families.";
};
packages = mkOption {
type = listOf package;
default = with pkgs; [ (nerdfonts.override { fonts = [ "JetBrainsMono" ]; }) ];
description = "The monospace font packages.";
};
};
emoji = {
names = mkOption {
type = listOf str;
default = [
"Noto Emoji"
"Font Awesome"
];
description = "The emoji font families.";
};
packages = mkOption {
type = listOf package;
default = with pkgs; [
noto-fonts-color-emoji
font-awesome
];
description = "The emoji font packages.";
};
};
size = mkOption {
type = ints.positive;
default = 12;
description = "The font size.";
};
};
icon = {
names = mkOption {
type = listOf str;
default = [ "Adwaita" ];
description = "The icon theme names.";
};
packages = mkOption {
type = listOf package;
default = with pkgs; [
adwaita-icon-theme
nixos-icons
];
description = "The icon theme packages.";
};
};
cursor = {
names = mkOption {
type = listOf str;
default = [ "Adwaita" ];
description = "The cursor names.";
};
packages = mkOption {
type = listOf package;
default = with pkgs; [ adwaita-icon-theme ];
description = "The cursor theme packages.";
};
size = mkOption {
type = ints.positive;
default = 32;
description = "The cursor size.";
};
};
};
config = lib.mkIf cfg.enable {
home = {
packages =
[ cfg.pkg ]
++ cfg.font.sansSerif.packages
++ cfg.font.serif.packages
++ cfg.font.monospace.packages
++ cfg.font.emoji.packages
++ cfg.icon.packages
++ cfg.cursor.packages;
pointerCursor = {
name = builtins.head cfg.cursor.names;
package = builtins.head cfg.cursor.packages;
inherit (cfg.cursor) size;
};
};
fonts.fontconfig = {
enable = true;
defaultFonts = {
sansSerif = cfg.font.sansSerif.names;
serif = cfg.font.serif.names;
monospace = cfg.font.monospace.names;
emoji = cfg.font.emoji.names;
};
};
};
}

View File

@@ -0,0 +1,98 @@
[ ! -L "$CONFIG"/wallpaper ] && ln -sf "$DEFAULT_WALLPAPER" "$CONFIG"/wallpaper
[ ! -f "$CONFIG"/mode ] && echo "$DEFAULT_MODE" > "$CONFIG"/mode
set_wallpaper() {
if [ -f "$1" ]; then
WALLPAPER="$1"
else
echo "Invalid wallpaper path: $1"
exit 1
fi
}
set_mode() {
if [ "$1" = "light" ] || [ "$1" = "dark" ]; then
MODE="$1"
else
echo "Invalid mode: $1. Use 'light' or 'dark'."
exit 1
fi
}
toggle_mode() {
if [ "$(cat "$CONFIG"/mode)" = "light" ]; then
MODE="dark"
else
MODE="light"
fi
}
show_usage() {
echo "Usage: theme {toggle|light|dark|mode <mode>|wallpaper <file> [mode]}"
}
finish() {
[ -n "$WALLPAPER" ] && ln -sf "$WALLPAPER" "$CONFIG"/wallpaper
[ -n "$MODE" ] && echo "$MODE" > "$CONFIG"/mode
{
"$SWITCH"
} > /dev/null
}
WALLPAPER=""
MODE=""
if [ $# -eq 0 ]; then
finish
else
case "$1" in
toggle)
if [ $# -eq 1 ]; then
toggle_mode
else
show_usage
exit 1
fi
;;
light)
if [ $# -eq 1 ]; then
set_mode "light"
else
show_usage
exit 1
fi
;;
dark)
if [ $# -eq 1 ]; then
set_mode "dark"
else
show_usage
exit 1
fi
;;
mode)
if [ $# -eq 2 ]; then
set_mode "$2"
else
show_usage
exit 1
fi
;;
wallpaper)
if [ $# -ge 2 ] && [ $# -le 3 ]; then
set_wallpaper "$2"
[ $# -eq 3 ] && set_mode "$3"
else
show_usage
exit 1
fi
;;
*)
show_usage
exit 1
;;
esac
finish
fi

View File

@@ -0,0 +1,99 @@
{
user ? throw "user argument is required",
}:
{
config,
inputs,
lib,
pkgs,
...
}:
let
hmConfig = config.home-manager.users.${user.name};
in
{
home-manager.users.${user.name} = {
programs.vscode = {
enable = true;
mutableExtensionsDir = false;
extensions = with pkgs.vscode-extensions; [ naumovs.color-highlight ];
userSettings = {
"diffEditor.ignoreTrimWhitespace" = false;
"editor.accessibilitySupport" = "off";
"editor.cursorBlinking" = "phase";
"editor.cursorSmoothCaretAnimation" = "on";
"editor.fontFamily" = builtins.concatStringsSep ", " hmConfig.theme.font.monospace.names;
"editor.fontLigatures" = true;
"editor.fontSize" = hmConfig.theme.font.size;
"editor.formatOnPaste" = true;
"editor.formatOnSave" = true;
"editor.formatOnType" = true;
"editor.indentSize" = "tabSize";
"editor.inlineSuggest.enabled" = true;
"editor.largeFileOptimizations" = false;
"editor.linkedEditing" = true;
"editor.renderFinalNewline" = "on";
"editor.smoothScrolling" = true;
"editor.stickyScroll.enabled" = true;
"editor.suggestSelection" = "first";
"editor.tabSize" = 2;
"editor.unicodeHighlight.includeComments" = true;
"editor.unicodeHighlight.nonBasicASCII" = true;
"explorer.confirmDelete" = false;
"explorer.confirmDragAndDrop" = false;
"explorer.confirmPasteNative" = false;
"files.autoSave" = "afterDelay";
"files.eol" = "\n";
"files.insertFinalNewline" = true;
"files.trimFinalNewlines" = true;
"files.trimTrailingWhitespace" = true;
"git.allowForcePush" = true;
"git.alwaysSignOff" = true;
"git.autofetch" = "all";
"git.closeDiffOnOperation" = true;
"git.confirmForcePush" = false;
"git.confirmSync" = false;
"git.enableCommitSigning" = true;
"git.enableSmartCommit" = true;
"git.ignoreRebaseWarning" = true;
"git.openRepositoryInParentFolders" = "always";
"git.path" = lib.meta.getExe pkgs.git;
"mergeEditor.diffAlgorithm" = "advanced";
"open-in-browser.default" = "firefox";
"security.workspace.trust.enabled" = false;
"telemetry.telemetryLevel" = "off";
"terminal.external.linuxExec" = "kitty";
"terminal.integrated.confirmOnExit" = "hasChildProcesses";
"terminal.integrated.copyOnSelection" = true;
"terminal.integrated.fontFamily" = builtins.concatStringsSep ", " hmConfig.theme.font.monospace.names;
"terminal.integrated.fontSize" = hmConfig.theme.font.size;
"window.autoDetectHighContrast" = false;
"window.menuBarVisibility" = "toggle";
"workbench.editor.historyBasedLanguageDetection" = true;
"workbench.list.smoothScrolling" = true;
};
};
imports = [ ./langs/nix.nix ];
home.persistence = {
"/persist${user.home}".directories = [ ".config/Code" ];
# Bastard: https://github.com/microsoft/vscode/issues/3884
"/cache${user.home}".directories = [
".config/Code/Cache"
".config/Code/CachedConfigurations"
".config/Code/CachedData"
".config/Code/CachedExtensionVSIXs"
".config/Code/CachedExtensions"
".config/Code/CachedProfilesData"
".config/Code/Code Cache"
".config/Code/DawnCache"
".config/Code/GPUCache"
".config/Code/Service Worker/CacheStorage"
".config/Code/Service Worker/ScriptCache"
];
};
};
}

View File

@@ -0,0 +1,16 @@
{ pkgs, ... }:
{
programs.vscode = {
userSettings = {
"nix.enableLanguageServer" = true;
"nix.formatterPath" = "nixpkgs-fmt";
"nix.serverSettings" = { };
};
extensions = with pkgs; with vscode-extensions; [ jnoortheen.nix-ide ];
};
home.packages = with pkgs; [
nil
nixpkgs-fmt
];
}

View File

@@ -0,0 +1,7 @@
{
user ? throw "user argument is required",
}:
{ pkgs, ... }:
{
home-manager.users.${user.name}.home.packages = with pkgs; [ wev ];
}

View File

@@ -0,0 +1,13 @@
{
user ? throw "user argument is required",
}:
{ config, ... }:
let
hmConfig = config.home-manager.users.${user.name};
in
{
home-manager.users.${user.name} = {
home.pointerCursor.x11.enable = true;
xresources.path = "${hmConfig.xdg.configHome}/X11/xresources";
};
}

View File

@@ -0,0 +1,26 @@
{ lib, ... }:
let
userOptions =
with lib;
with types;
{ config, ... }:
{
options.email = mkOption {
type = nullOr str;
description = "Email address of the user.";
};
options.fullName = mkOption {
type = nullOr str;
description = "Full name of the user.";
};
};
in
{
options =
with lib;
with types;
{
users.users = mkOption { type = attrsOf (submodule userOptions); };
};
}