feat: ...get internet again. git-hooks.nix adopt

This commit is contained in:
Kat Inskip 2025-08-18 15:13:47 -07:00
parent 7a0f09e700
commit e00ec8f2f2
Signed by: kat
GPG key ID: 465E64DECEA8CF0F
116 changed files with 1157 additions and 4681 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
/.pre-commit-config.yaml
*.pyc
venv/
.direnv/

View file

@ -6,10 +6,8 @@ let
sha256 = flake-compat-node.locked.narHash;
};
flake = (
import flake-compat {
flake = import flake-compat {
src = ./.;
}
);
};
in
flake.defaultNix

291
flake.lock generated
View file

@ -150,15 +150,15 @@
]
},
"locked": {
"lastModified": 1752507097,
"narHash": "sha256-/JlfJOzHs7tJpFp6bw1AF7hO9FMMgLjQgtCaIK/jA2M=",
"owner": "kittywitch",
"lastModified": 1755545956,
"narHash": "sha256-/dqfdlsu8jonCbwWTlYXC4vVU4/71Yvz/NZMu1NMwos=",
"owner": "chaotic-cx",
"repo": "nyx",
"rev": "721f290b311f88eef85e8415f445fe5f90bf9155",
"rev": "f14fadaa130cc0e222271acde3dddc3596b97c69",
"type": "github"
},
"original": {
"owner": "kittywitch",
"owner": "chaotic-cx",
"ref": "nyxpkgs-unstable",
"repo": "nyx",
"type": "github"
@ -223,11 +223,11 @@
]
},
"locked": {
"lastModified": 1751313918,
"narHash": "sha256-HsJM3XLa43WpG+665aGEh8iS8AfEwOIQWk3Mke3e7nk=",
"lastModified": 1755275010,
"narHash": "sha256-lEApCoWUEWh0Ifc3k1JdVjpMtFFXeL2gG1qvBnoRc2I=",
"owner": "lnl7",
"repo": "nix-darwin",
"rev": "e04a388232d9a6ba56967ce5b53a8a6f713cdfcf",
"rev": "7220b01d679e93ede8d7b25d6f392855b81dd475",
"type": "github"
},
"original": {
@ -354,11 +354,11 @@
]
},
"locked": {
"lastModified": 1753121425,
"narHash": "sha256-TVcTNvOeWWk1DXljFxVRp+E0tzG1LhrVjOGGoMHuXio=",
"lastModified": 1754487366,
"narHash": "sha256-pHYj8gUBapuUzKV/kN/tR3Zvqc7o6gdFB9XKXIp1SQ8=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "644e0fc48951a860279da645ba77fe4a6e814c5e",
"rev": "af66ad14b28a127c5c0f3bbb298218fc63528a18",
"type": "github"
},
"original": {
@ -508,7 +508,52 @@
"type": "github"
}
},
"git-hooks": {
"inputs": {
"flake-compat": [
"flake-compat"
],
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1755446520,
"narHash": "sha256-I0Ok1OGDwc1jPd8cs2VvAYZsHriUVFGIUqW+7uSsOUM=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "4b04db83821b819bbbe32ed0a025b31e7971f22e",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"git-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"gitignore_2": {
"inputs": {
"nixpkgs": [
"lanzaboote",
@ -571,11 +616,11 @@
]
},
"locked": {
"lastModified": 1753132348,
"narHash": "sha256-0i3jU9AHuNXb0wYGzImnVwaw+miE0yW13qfjC0F+fIE=",
"lastModified": 1755538029,
"narHash": "sha256-XVsragfuN8A/tMiPToejH7RofH15toeIGhlXraX+yBo=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "e4bf85da687027cfc4a8853ca11b6b86ce41d732",
"rev": "bf450a0844e80e6aa22652d3f3728f20cd974527",
"type": "github"
},
"original": {
@ -676,11 +721,11 @@
]
},
"locked": {
"lastModified": 1752340638,
"narHash": "sha256-9+vBdRt/jg8fAll1VD3NXBibkRq9F8Wq/mW45I5jlvc=",
"lastModified": 1755151620,
"narHash": "sha256-fVMalQZ+tRXR8oue2SdWu4CdlsS2NII+++rI40XQ8rU=",
"owner": "Jovian-Experiments",
"repo": "Jovian-NixOS",
"rev": "1129c951dcc2a269a12cb74d64bd64e44e724ecb",
"rev": "16e12d22754d97064867006acae6e16da7a142a6",
"type": "github"
},
"original": {
@ -785,11 +830,11 @@
]
},
"locked": {
"lastModified": 1753282722,
"narHash": "sha256-KYMUrTV7H/RR5/HRnjV5R3rRIuBXMemyJzTLi50NFTs=",
"lastModified": 1755512154,
"narHash": "sha256-/ySltwXacRewWwY/ze3TandOYMTH8GB11JQGazvw23c=",
"ref": "release-2.93",
"rev": "46a9e8fcfe4be72b4c7c8082ee11d2c42da1e873",
"revCount": 149,
"rev": "6a343d03d6497aefe98013b215d21d06a59e4442",
"revCount": 152,
"type": "git",
"url": "https://git.lix.systems/lix-project/nixos-module"
},
@ -799,6 +844,30 @@
"url": "https://git.lix.systems/lix-project/nixos-module"
}
},
"microvm": {
"inputs": {
"flake-utils": [
"flake-utils"
],
"nixpkgs": [
"nixpkgs"
],
"spectrum": "spectrum"
},
"locked": {
"lastModified": 1755102374,
"narHash": "sha256-v6xhTSgnGQoF1a51BB6OQWN8HXiYbZtVL+54TRuk9zk=",
"owner": "microvm-nix",
"repo": "microvm.nix",
"rev": "0a5cda80e48191959cf5a9c0552532599ef2cee4",
"type": "github"
},
"original": {
"owner": "microvm-nix",
"repo": "microvm.nix",
"type": "github"
}
},
"minecraft": {
"inputs": {
"flake-compat": [
@ -812,11 +881,11 @@
]
},
"locked": {
"lastModified": 1753064794,
"narHash": "sha256-3EgmLyksi5Jpb54tNymeEBY8/h/G1Gf5HAQw4gm1d+8=",
"lastModified": 1755483699,
"narHash": "sha256-dj5cNx+WvDv5fbsE4h/Q6UuTttc/BHBE3BVGVn2TUNk=",
"owner": "Infinidoge",
"repo": "nix-minecraft",
"rev": "95db5df2b845b360d0a9b79cbec9f95290a93de9",
"rev": "aa5ed59e2570c7adfd6f5ca6ec08fff3140d7565",
"type": "github"
},
"original": {
@ -880,11 +949,11 @@
]
},
"locked": {
"lastModified": 1753122556,
"narHash": "sha256-6KjgmTc9nLjaI89Bx8kmwVCTK8y0oYkPCaSQqoz4RXk=",
"lastModified": 1755296276,
"narHash": "sha256-xvY9lYZHLp0xw+LTgZVmWFbVFl5O/M2eRVwB+MolaXY=",
"owner": "nvim-neorg",
"repo": "nixpkgs-neorg-overlay",
"rev": "5f9b264c26c0a95a94bf1dae4d23813f434abdfc",
"rev": "66b25e0d47de5830de00e91e119f00b7ac9b17e1",
"type": "github"
},
"original": {
@ -916,11 +985,11 @@
]
},
"locked": {
"lastModified": 1752935256,
"narHash": "sha256-KKaUEg1/ntHVsG61CkKFr2mfdsoK9Nj5FM/W1PBhe5o=",
"lastModified": 1755510252,
"narHash": "sha256-IPwAGaR9LO4LasxIFPqOTmIfliDsnzWVgzsaIekzRG4=",
"owner": "nix-community",
"repo": "nh",
"rev": "a90e3124111d9c3eb64e97a5334db09a8e2a4bae",
"rev": "8d690296fb3b898da565b33455a4227aed8a3133",
"type": "github"
},
"original": {
@ -943,11 +1012,11 @@
"xwayland-satellite-unstable": "xwayland-satellite-unstable"
},
"locked": {
"lastModified": 1753132162,
"narHash": "sha256-ycK2rB1kltXcrz5+dpldPngiYMukgaT2atwxhTjkIZQ=",
"lastModified": 1755424351,
"narHash": "sha256-xcorYLNdtLpb0wH5CPlUcpmYQUxeK95j1X855xQw+DY=",
"owner": "sodiboo",
"repo": "niri-flake",
"rev": "f7cc80e3ad7e34ac523ba401ece49c4151fc19ca",
"rev": "9aa137af01f05386e5bb5050e983750017007a66",
"type": "github"
},
"original": {
@ -976,11 +1045,11 @@
"niri-unstable": {
"flake": false,
"locked": {
"lastModified": 1752870529,
"narHash": "sha256-23DJk5EfEDCq7Xy1QELcayG0VxbbWpdQ6t7jbhae1Ok=",
"lastModified": 1755419373,
"narHash": "sha256-EFH3zbpyLYjEboNV2Lmkxf9joEuFCmeYX+MMLRPStpg=",
"owner": "YaLTeR",
"repo": "niri",
"rev": "fefc0bc0a71556eb75352e2b611e50eb5d3bf9c2",
"rev": "a6febb86aa5af0df7bf2792ca027ef95a503d599",
"type": "github"
},
"original": {
@ -1015,11 +1084,11 @@
]
},
"locked": {
"lastModified": 1753113952,
"narHash": "sha256-v2mLDtNbfSKDiogwMB6RxKsyt0dfSjs2v6PpsdEbMPI=",
"lastModified": 1755396822,
"narHash": "sha256-gID7ynpJuflQ/+ibrhYUWybiGPduNvvMJSk27oqfK24=",
"owner": "fufexan",
"repo": "nix-gaming",
"rev": "8b7d06a10c9cbf41b66ca6033bb4b5175be36d76",
"rev": "f2bf778502254d8852402a83ae346fd803095ccc",
"type": "github"
},
"original": {
@ -1058,11 +1127,11 @@
]
},
"locked": {
"lastModified": 1752985182,
"narHash": "sha256-sX8Neff8lp3TCHai6QmgLr5AD8MdsQQX3b52C1DVXR8=",
"lastModified": 1755404379,
"narHash": "sha256-Q6ZxZDBmD/B988Jjbx7/NchxOKIpOKBBrx9Yb0zMzpQ=",
"owner": "Mic92",
"repo": "nix-index-database",
"rev": "fafdcb505ba605157ff7a7eeea452bc6d6cbc23c",
"rev": "ebbc1c05f786ae39bb5e04e57bf2c10c44a649e3",
"type": "github"
},
"original": {
@ -1114,11 +1183,11 @@
]
},
"locked": {
"lastModified": 1752775021,
"narHash": "sha256-TeI0RNfcpzDi+E0lHHwaYECTfmlsnA0ogUEohyrRJbs=",
"lastModified": 1755531224,
"narHash": "sha256-gy3E/WgenQbZUWH/DRgnDvAb//fr6iiG6PPnL7OFtZg=",
"owner": "nix-community",
"repo": "nixos-cli",
"rev": "183be79f8610ef0bee62a09e86d6428b1dfdf446",
"rev": "f1d16001cb2f32d61cd49e527d111c43c457e629",
"type": "github"
},
"original": {
@ -1129,11 +1198,11 @@
},
"nixos-hardware": {
"locked": {
"lastModified": 1753122741,
"narHash": "sha256-nFxE8lk9JvGelxClCmwuJYftbHqwnc01dRN4DVLUroM=",
"lastModified": 1755330281,
"narHash": "sha256-aJHFJWP9AuI8jUGzI77LYcSlkA9wJnOIg4ZqftwNGXA=",
"owner": "NixOS",
"repo": "nixos-hardware",
"rev": "cc66fddc6cb04ab479a1bb062f4d4da27c936a22",
"rev": "3dac8a872557e0ca8c083cdcfc2f218d18e113b0",
"type": "github"
},
"original": {
@ -1158,11 +1227,11 @@
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1752974445,
"narHash": "sha256-jj/HBJFSapTk4LfeJgNLk2wEE2BO6dgBYVRbXMNOCeM=",
"lastModified": 1754788789,
"narHash": "sha256-x2rJ+Ovzq0sCMpgfgGaaqgBSwY+LST+WbZ6TytnT9Rk=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "9100109c11b6b5482ea949c980b86e24740dca08",
"rev": "a73b9c743612e4244d865a2fdee11865283c04e6",
"type": "github"
},
"original": {
@ -1203,11 +1272,11 @@
]
},
"locked": {
"lastModified": 1753062663,
"narHash": "sha256-o58S/1S0z3HEedWys5APgYysIA50CFcWVzrRDjyJqN8=",
"lastModified": 1755481576,
"narHash": "sha256-XMxUEKhucJR6v/OBv5PW4xZOvdAWrF+SSct2s+POoz0=",
"owner": "nix-community",
"repo": "nixpkgs-xr",
"rev": "de4b6cad5730a71a433077bcc091e6cae5c6c67f",
"rev": "cc31049a24af3cf85a85cc66bb72dda88b2512e9",
"type": "github"
},
"original": {
@ -1218,11 +1287,11 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1751984180,
"narHash": "sha256-LwWRsENAZJKUdD3SpLluwDmdXY9F45ZEgCb0X+xgOL0=",
"lastModified": 1755186698,
"narHash": "sha256-wNO3+Ks2jZJ4nTHMuks+cxAiVBGNuEBXsT29Bz6HASo=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9807714d6944a957c2e036f84b0ff8caf9930bc0",
"rev": "fbcf476f790d8a217c3eab4e12033dc4a0f6d23c",
"type": "github"
},
"original": {
@ -1295,11 +1364,11 @@
]
},
"locked": {
"lastModified": 1753132846,
"narHash": "sha256-ni+4j0pTEkvqpNO/E9RKsOKJSVYdYEApdCoij1hPt3g=",
"lastModified": 1755551744,
"narHash": "sha256-YbIFASCxQicuwfTLjCFAQ/IZDJ8R5+QnnmxjUejgjVs=",
"owner": "nix-community",
"repo": "NUR",
"rev": "a6f29e5548472bf073580f34f06ddac62d930985",
"rev": "d57e71d6f02cf7614577b1f5e5bff948c48aa361",
"type": "github"
},
"original": {
@ -1314,7 +1383,7 @@
"lanzaboote",
"flake-compat"
],
"gitignore": "gitignore",
"gitignore": "gitignore_2",
"nixpkgs": [
"lanzaboote",
"nixpkgs"
@ -1335,33 +1404,6 @@
"type": "github"
}
},
"push2talk": {
"inputs": {
"flake-utils": [
"flake-utils"
],
"naersk": [
"naersk"
],
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1718742709,
"narHash": "sha256-Dr0K3NB6HCpdQ4Dm1WzWmlPCn7nq7JRB7sZVXjtVYB8=",
"owner": "cyrinux",
"repo": "push2talk",
"rev": "046aa4ef25b08257e17a31939faed617e5372562",
"type": "github"
},
"original": {
"owner": "cyrinux",
"ref": "main",
"repo": "push2talk",
"type": "github"
}
},
"rbw-bitw": {
"inputs": {
"flakelib": [
@ -1405,11 +1447,13 @@
"flake-utils": "flake-utils",
"flake-utils-plus": "flake-utils-plus",
"flakelib": "flakelib",
"git-hooks": "git-hooks",
"home-manager": "home-manager",
"infrastructure": "infrastructure",
"konawall-py": "konawall-py",
"lanzaboote": "lanzaboote",
"lix-module": "lix-module",
"microvm": "microvm",
"minecraft": "minecraft",
"naersk": "naersk",
"neorg-overlay": "neorg-overlay",
@ -1430,7 +1474,6 @@
"norg": "norg",
"norg-meta": "norg-meta",
"nur": "nur",
"push2talk": "push2talk",
"rbw-bitw": "rbw-bitw",
"rust": "rust",
"rust-overlay": "rust-overlay",
@ -1491,11 +1534,11 @@
]
},
"locked": {
"lastModified": 1753066249,
"narHash": "sha256-j2UBrfDRIePGx3532Bbb9UeosNX2F73hfOAHtmACfnM=",
"lastModified": 1755485198,
"narHash": "sha256-C3042ST2lUg0nh734gmuP4lRRIBitA6Maegg2/jYRM4=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "0751b65633a1785743ca44fd7c14a633c54c1f91",
"rev": "aa45e63d431b28802ca4490cfc796b9e31731df7",
"type": "github"
},
"original": {
@ -1563,11 +1606,11 @@
]
},
"locked": {
"lastModified": 1752544651,
"narHash": "sha256-GllP7cmQu7zLZTs9z0J2gIL42IZHa9CBEXwBY9szT0U=",
"lastModified": 1754988908,
"narHash": "sha256-t+voe2961vCgrzPFtZxha0/kmFSHFobzF00sT8p9h0U=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "2c8def626f54708a9c38a5861866660395bb3461",
"rev": "3223c7a92724b5d804e9988c6b447a0d09017d48",
"type": "github"
},
"original": {
@ -1576,6 +1619,22 @@
"type": "github"
}
},
"spectrum": {
"flake": false,
"locked": {
"lastModified": 1754675037,
"narHash": "sha256-afS08F7lfMUBR4qrBxinN1kuxu+DoHQ5TPNVp9VS/OA=",
"ref": "refs/heads/main",
"rev": "586577f3015397afacd83bc185454f4cc3c8028f",
"revCount": 955,
"type": "git",
"url": "https://spectrum-os.org/git/spectrum"
},
"original": {
"type": "git",
"url": "https://spectrum-os.org/git/spectrum"
}
},
"spicetify-nix": {
"inputs": {
"nixpkgs": [
@ -1586,11 +1645,11 @@
]
},
"locked": {
"lastModified": 1752986956,
"narHash": "sha256-1AK8+W7d5eNyGRkcWHa+9oIChLJbY6jt7ujSJo+ft4M=",
"lastModified": 1755405549,
"narHash": "sha256-0vJD6WhL1jfXbnpH6r8yr1RgzB8mGFWIWokKHaJMJ/4=",
"owner": "Gerg-L",
"repo": "spicetify-nix",
"rev": "51ac0aee7e7ee21ca0874b913f07f9004bc9311f",
"rev": "df1f5d4c0633040937358755defff9f07e9c0a73",
"type": "github"
},
"original": {
@ -1606,11 +1665,11 @@
]
},
"locked": {
"lastModified": 1706552916,
"narHash": "sha256-Dh7qUXNTjmvwMOikm8EAarcmxCCiLaXHAFEeWKsNsHk=",
"lastModified": 1755319302,
"narHash": "sha256-RlRbcRXRgvt/gCVb3FnhLzARRiFNNangaw2GMaXhKsQ=",
"owner": "flakelib",
"repo": "std",
"rev": "c5cffcaff4b82b353462cf49c1ae950b7c87bf78",
"rev": "53aa63f4aaac4a4939ae132ee17f42a10a02dad0",
"type": "github"
},
"original": {
@ -1664,11 +1723,11 @@
"tinted-zed": "tinted-zed"
},
"locked": {
"lastModified": 1753553562,
"narHash": "sha256-CpTwdsrPU3UFy95Btg56RcVMgNpnw3C0DYTznE5aRq4=",
"lastModified": 1755546184,
"narHash": "sha256-KxRj/8SydDk3gzamS0VEewo5pu8JAYhSZ5GPcImPGNQ=",
"owner": "nix-community",
"repo": "stylix",
"rev": "af85565aba0f4749cb18b118a7333a0745920950",
"rev": "9810b32b9b7520e3b37358ff8e793fb5034c3299",
"type": "github"
},
"original": {
@ -1821,11 +1880,11 @@
]
},
"locked": {
"lastModified": 1753006367,
"narHash": "sha256-tzbhc4XttkyEhswByk5R38l+ztN9UDbnj0cTcP6Hp9A=",
"lastModified": 1754847726,
"narHash": "sha256-2vX8QjO5lRsDbNYvN9hVHXLU6oMl+V/PsmIiJREG4rE=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "421b56313c65a0815a52b424777f55acf0b56ddf",
"rev": "7d81f6fb2e19bf84f1c65135d1060d829fae2408",
"type": "github"
},
"original": {
@ -1852,11 +1911,11 @@
},
"locked": {
"dir": "nix",
"lastModified": 1752411069,
"narHash": "sha256-V1zJsyxPtWmqsggOm0d/rhgNr+Jwb+l+PSTFC2RWZ0o=",
"lastModified": 1753901871,
"narHash": "sha256-l/ZFg1KW506CvkQKstNkEHnfY7p9aX5q4L6rFmxiKbo=",
"owner": "wez",
"repo": "wezterm",
"rev": "85c587f9f3d8be49dfa252da116fc9ca290df113",
"rev": "6a493f88fab06a792308e0c704790390fd3c6232",
"type": "github"
},
"original": {
@ -1887,11 +1946,11 @@
"xwayland-satellite-unstable": {
"flake": false,
"locked": {
"lastModified": 1752338000,
"narHash": "sha256-Fxlp/yKtynug0jyuauAmvZU2SzHCfwlwWf85j+IvQ0U=",
"lastModified": 1755219541,
"narHash": "sha256-yKV6xHaPbEbh5RPxAJnb9yTs1wypr7do86hFFGQm1w8=",
"owner": "Supreeeme",
"repo": "xwayland-satellite",
"rev": "ba78881a68182ce338041846164cbfed0d70935c",
"rev": "5a184d435927c3423f0ad189ea2b490578450fb7",
"type": "github"
},
"original": {
@ -1908,11 +1967,11 @@
]
},
"locked": {
"lastModified": 1753069499,
"narHash": "sha256-YtgY0ueqKNrBma4Euu8WH23BhUkBujirJDMDE1KujnU=",
"lastModified": 1755484558,
"narHash": "sha256-1dlhluaqrePy1L8ShBCkiF/KF9ci5tSZzdUI60NjzOI=",
"owner": "0xc000022070",
"repo": "zen-browser-flake",
"rev": "c64b94235ae24e3b9e01a08f0331d8bb0e5b037a",
"rev": "d169f16140842d7ba3183c0321f984368bdd2ee3",
"type": "github"
},
"original": {

View file

@ -8,6 +8,13 @@
nixpkgs.follows = "nixpkgs";
};
};
git-hooks = {
url = "github:cachix/git-hooks.nix";
inputs = {
flake-compat.follows = "flake-compat";
nixpkgs.follows = "nixpkgs";
};
};
nix-flatpak = {
url = "github:gmodena/nix-flatpak/?ref=latest";
};
@ -31,6 +38,13 @@
# inputs.nixpkgs.follows = "nixpkgs";
#};
};
microvm = {
url = "github:microvm-nix/microvm.nix";
inputs = {
nixpkgs.follows = "nixpkgs";
flake-utils.follows = "flake-utils";
};
};
stylix = {
url = "github:nix-community/stylix";
inputs = {
@ -126,8 +140,7 @@
};
};
chaotic = {
#url = "path:/home/kat/Projects/nyx";
url = "github:kittywitch/nyx/nyxpkgs-unstable";
url = "github:chaotic-cx/nyx/nyxpkgs-unstable";
inputs = {
#nixpkgs.follows = "nixpkgs";
rust-overlay.follows = "rust-overlay";
@ -192,14 +205,6 @@
nixpkgs.follows = "nixpkgs";
};
};
push2talk = {
url = "github:cyrinux/push2talk/main";
inputs = {
nixpkgs.follows = "nixpkgs";
flake-utils.follows = "flake-utils";
naersk.follows = "naersk";
};
};
wezterm = {
url = "github:wez/wezterm/main?dir=nix";
inputs = {

View file

@ -1,57 +0,0 @@
{
config,
inputs,
pkgs,
...
}: let
konawallConfig = {
interval = 3000;
rotate = true;
source = "konachan";
tags = [
"rating:s"
"nobody"
"score:>=50"
"width:>=1500"
];
logging = {
file = "INFO";
console = "DEBUG";
};
};
in {
home.file."Library/Application Support/konawall/config.toml".source = (pkgs.formats.toml {}).generate "konawall-config" konawallConfig;
launchd.agents.konawall = {
enable = true;
config = let
konawallInitialize = pkgs.writeScriptBin "konawall-initialize" ''
#!/usr/bin/env bash
set -xeuo pipefail
# get a temporary directory
tmpDir=$(mktemp -d)
# copy the repository to the temporary directory recursively without keeping the permissions from the nix store
${pkgs.coreutils}/bin/cp -r --no-preserve=mode,ownership "${inputs.konawall-py.outPath}" "$tmpDir/konawall"
# change directory to the copy
cd $tmpDir/konawall
# install the dependencies
${pkgs.poetry}/bin/poetry install
# run the package
${pkgs.poetry}/bin/poetry run gui
'';
in {
# yeah if https://github.com/NixOS/nixpkgs/issues/233265 and https://github.com/NixOS/nixpkgs/issues/101360
# and https://github.com/NixOS/nixpkgs/issues/105156 were ok we might be able to do this
#Program = "${inputs.konawall-py.packages.${pkgs.system}.konawall-py}/bin/konawall";
#ProgramArguments = ["${inputs.konawall-py.packages.${pkgs.system}.konawall-py}/bin/konawall"];
# it's unfortunate that this has to be done this way, for the most part.
ProgramArguments = [
"/usr/bin/env"
"bash"
"${konawallInitialize}/bin/konawall-initialize"
];
RunAtLoad = true;
KeepAlive = true;
};
};
}

View file

@ -1,35 +0,0 @@
_: {
dconf = {
enable = true;
settings = {
"org/gnome/shell" = {
favorite-apps = [
"firefox.desktop"
"thunderbird.desktop"
"nheko.desktop"
"discord.desktop"
"signal-desktop.desktop"
"org.telegram.desktop.desktop"
"codium.desktop"
"obsidian.desktop"
"org.wezfurlong.wezterm.desktop"
"spotify.desktop"
"steam.desktop"
"org.gnome.Nautilus.desktop"
"bitwarden.desktop"
];
};
"org/gnome/desktop/interface" = {
color-scheme = "prefer-dark";
enable-hot-corners = false;
};
"org/gnome/desktop/wm/preferences" = {
workspace-names = ["Main"];
resize-with-right-button = true;
};
"org/gnome/desktop/input-sources" = {
xkb-options = ["terminate:ctrl_alt_bksp" "caps:ctrl_modifier"];
};
};
};
}

View file

@ -1,39 +0,0 @@
{pkgs, ...}: {
dconf = {
settings = {
"org/gnome/shell" = {
disable-user-extensions = false;
# `gnome-extensions list` for a list
enabled-extensions = [
"user-theme@gnome-shell-extensions.gcampax.github.com"
"Vitals@CoreCoding.com"
"dash-to-panel@jderose9.github.com"
"space-bar@luchrioh"
"appindicatorsupport@rgcjonas.gmail.com"
"arcmenu@arcmenu.com"
"date-menu-formatter@marcinjakubowski.github.com"
];
};
"org/gnome/shell/extensions/daerte-menu-formatter" = {
pattern = "y-MM-dd HH:mm:ss ";
"font-size" = "12";
};
"org/gnome/shell/extensions/vitals" = {
"hot-sensors" = ["_memory_usage_" "_system_load_1m_" "__network-rx_max__" "_temperature_k10temp_tctl_"];
};
};
};
home.packages = with pkgs.gnomeExtensions; [
pkgs.arcmenu
space-bar
user-themes
tray-icons-reloaded
appindicator
caffeine
vitals
dash-to-panel
date-menu-formatter
];
}

View file

@ -1,21 +0,0 @@
{pkgs, ...}: {
gtk = {
enable = true;
iconTheme = {
name = "Numix-Square";
package = pkgs.numix-icon-theme-square;
};
theme = {
name = "Arc-Dark";
package = pkgs.arc-theme;
};
cursorTheme = {
name = "Numix-Cursor";
package = pkgs.numix-cursor-theme;
};
};
home.sessionVariables.GTK_THEME = "Arc-Dark";
}

View file

@ -1,42 +0,0 @@
{
config,
pkgs,
inputs,
...
}: let
konawallConfig = {
interval = 30 * 60;
rotate = true;
source = "konachan";
tags = [
"rating:s"
"touhou"
"score:>=50"
"width:>=1500"
];
logging = {
file = "INFO";
console = "DEBUG";
};
};
in {
xdg.configFile = {
"konawall/config.toml".source = (pkgs.formats.toml {}).generate "konawall-config" konawallConfig;
};
systemd.user.services.konawall-py-gnome = {
Unit = {
Description = "konawall-py";
X-Restart-Triggers = [(toString config.xdg.configFile."konawall/config.toml".source)];
After = ["gnome-session.target" "network-online.target"];
Environment = [
"PYSTRAY_BACKEND=gtk"
];
};
Service = {
ExecStart = "${inputs.konawall-py.packages.${pkgs.system}.konawall-py}/bin/konawall";
Restart = "on-failure";
RestartSec = "1s";
};
Install = {WantedBy = ["gnome-session.target"];};
};
}

View file

@ -1,15 +0,0 @@
{
lib,
pkgs,
...
}: let
inherit (lib.strings) fileContents;
in {
home.sessionVariables.GSM_SKIP_SSH_AGENT_WORKAROUND = "1";
# Disable gnome-keyring ssh-agent
xdg.configFile."autostart/gnome-keyring-ssh.desktop".text = ''
${fileContents "${pkgs.gnome-keyring}/etc/xdg/autostart/gnome-keyring-ssh.desktop"}
Hidden=true
'';
}

View file

@ -1,8 +0,0 @@
{pkgs, ...}: {
home.pointerCursor = {
enable = true;
package = pkgs.graphite-cursors;
size = 16;
name = "graphite-dark";
};
}

View file

@ -1,29 +0,0 @@
{pkgs, ...}: {
services.hypridle = {
enable = false;
listeners = [
{
timeout = 150;
onTimeout = "${pkgs.brightnessctl}/bin/brightnessctl -s set 5";
onResume = "${pkgs.brightnessctl}/bin/brightnessctl -r";
}
{
timeout = 300;
onTimeout = "${pkgs.systemd}/bin/loginctl lock-session";
}
{
timeout = 330;
onTimeout = "${pkgs.hyprland}/bin/hyprctl dispatch dpms off";
onResume = "${pkgs.hyprland}/bin/hyprctl dispatch dpms on";
}
{
timeout = 600;
onTimeout = "${pkgs.systemd}/bin/systemctl suspend";
}
];
beforeSleepCmd = "${pkgs.systemd}/bin/loginctl lock-session";
afterSleepCmd = "${pkgs.hyprland}/bin/hyprctl dispatch dpms on";
lockCmd = "pidof hyprlock || ${pkgs.hyprlock}/bin/hyprlock";
unlockCmd = "${pkgs.psmisc}/bin/killall hyprlock";
};
}

View file

@ -1,249 +0,0 @@
{
std,
parent,
lib,
pkgs,
inputs,
...
}: let
inherit (std) list;
in {
home.packages = with pkgs; [
grimblast
wl-clipboard
wlr-randr
wl-screenrec
slurp
grim
swww
pavucontrol
hyprpicker
brightnessctl
playerctl
glib
pcmanfm
];
services.hyprpolkitagent.enable = true;
services.swww.enable = true;
wayland.windowManager.hyprland = let
import-gsettings = pkgs.writeShellScriptBin "import-gsettings" ''
# usage: import-gsettings
config="''${XDG_CONFIG_HOME:-$HOME/.config}/gtk-3.0/settings.ini"
if [ ! -f "$config" ]; then exit 1; fi
gnome_schema="org.gnome.desktop.interface"
gtk_theme="$(grep 'gtk-theme-name' "$config" | sed 's/.*\s*=\s*//')"
icon_theme="$(grep 'gtk-icon-theme-name' "$config" | sed 's/.*\s*=\s*//')"
cursor_theme="$(grep 'gtk-cursor-theme-name' "$config" | sed 's/.*\s*=\s*//')"
font_name="$(grep 'gtk-font-name' "$config" | sed 's/.*\s*=\s*//')"
${pkgs.glib}/bin/gsettings set "$gnome_schema" gtk-theme "$gtk_theme"
${pkgs.glib}/bin/gsettings set "$gnome_schema" icon-theme "$icon_theme"
${pkgs.glib}/bin/gsettings set "$gnome_schema" cursor-theme "$cursor_theme"
${pkgs.glib}/bin/gsettings set "$gnome_schema" font-name "$font_name"
'';
in {
enable = true;
systemd = {
enable = false;
variables = ["--all"];
enableXdgAutostart = true;
extraCommands = [
"systemctl --user stop graphical-session.target"
"systemctl --user start hyprland-session.target"
];
};
xwayland.enable = true;
package = inputs.hyprland.packages.${pkgs.system}.hyprland;
settings = {
# TODO: break it up
windowrule = [
"suppressevent fullscreen, class:steam_app_default"
"workspace 2, class:steam_app_default"
"suppressevent maximize, class:.*"
"tile, class:battle\.net\.exe"
"renderunfocused, class:discord, initialTitle:Discord"
"unset, title:Wine System Tray"
"workspace special:hidden silent, title:Wine System Tray"
"noinitialfocus, title:Wine System Tray"
];
"$mod" = "SUPER";
input = {
kb_options = "ctrl:nocaps";
accel_profile = "flat";
sensitivity = 1.0;
scroll_factor = 1.0;
};
cursor = {
use_cpu_buffer = true;
};
workspace = let
commonOptions = "gapsin:0,gapsout:0,rounding:false";
in
["1,monitor:DP-1,default:true,${commonOptions}"]
++ (list.map (
workspace: "${toString workspace},monitor:DP-1${commonOptions}"
) (list.range 2 10))
++ ["11,monitor:DP-2,default:true"]
++ (list.map (
workspace: "${toString workspace},monitor:DP-2${commonOptions}"
) (list.range 12 20));
/*
list.concat (list.generate (
x: let
ws = let
c = (x + 1) / 10;
in
builtins.toString (x + 1 - (c * 10));
in [
"${toString x},monitor:DP-1"
"${toString (x + 10)},monitor:DP-2${commonOptions}"
]
)
10);
*/
env = [
"MOZ_ENABLE_WAYLAND,1"
"XDG_CURRENT_DESKTOP,Hyprland"
"GDK_BACKEND,wayland,x11"
"CLUTTER_BACKEND,wayland"
];
render.direct_scanout = false;
debug.disable_logs = false;
exec-once = [
"${pkgs.swww}/bin/swww init"
"${pkgs.hypridle}/bin/hypridle"
"${pkgs.dbus}/bin/dbus-update-activation-environment --all"
"${pkgs.libsForQt5.polkit-kde-agent}/bin/polkit-kde-agent"
"${pkgs.networkmanagerapplet}/bin/nm-applet"
"${pkgs.mako}/bin/mako"
"${pkgs.udiskie}/bin/udiskie &"
"${pkgs.pasystray}/bin/pasystray"
"${pkgs.systemd}/bin/systemctl restart waybar --user"
"${pkgs.systemd}/bin/systemctl restart konawall-py --user"
"legcord --enable-features=WaylandLinuxDrmSyncobj,UseOzonePlatform --ozone-platform=wayland"
"spotify --enable-features=WaylandLinuxDrmSyncobj,UseOzonePlatform --ozone-platform=wayland"
];
group.groupbar = {
font_family = "Monaspace Krypton";
font_size = 12;
};
exec = [
"${import-gsettings}/bin/import-gsettings"
];
xwayland = {
force_zero_scaling = true;
};
bindm = [
"$mod, mouse:272, movewindow"
"$mod, mouse:273, resizewindow"
"$mod ALT, mouse:272, resizewindow"
];
bindl = [
", XF86AudioPlay, exec, playerctl play-pause"
", XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"
", XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"
];
binde = [
", XF86AudioRaiseVolume, exec, wpctl set-volume -l 1.5 @DEFAULT_AUDIO_SINK@ 5%+"
", XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"
", XF86MonBrightnessUp, exec, ${pkgs.brightnessctl}/bin/brightnessctl -c backlight set 5%+"
", XF86MonBrightnessDown, exec, ${pkgs.brightnessctl}/bin/brightnessctl -c backlight set 5%-"
];
bind = let
uwsmCmd = lib.optionalString parent.programs.uwsm.enable "uwsm app -- ";
uwsmApp = cmd: uwsmCmd + cmd;
uwsmSingleApp = cmd: "pgrep ${cmd} || ${uwsmCmd + cmd}";
in
[
", XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"
", XF86AudioPlay, exec, ${pkgs.playerctl}/bin/playerctl play-pause"
", XF86AudioNext, exec, ${pkgs.playerctl}/bin/playerctl next"
", XF86AudioPrev, exec, ${pkgs.playerctl}/bin/playerctl prev"
"$mod, R, exec, wofi -t wezterm -IS drun"
"$mod SHIFT, R, exec, wofi -t wezterm -IS run"
"$mod, RETURN, exec, ${uwsmApp "wezterm"}"
"$mod, W, exec, ${uwsmApp "firefox"}"
"$mod, E, exec, ${uwsmApp "pcmanfm"}"
", Print, exec, ${uwsmSingleApp "grimblast"} copy area"
"CTRL ALT, DELETE, exec, ${uwsmApp "hyprctl kill"}"
"CTRL ALT SHIFT, DELETE, exec, loginctl terminate-user \"\""
"$mod SHIFT, E, exec, pkill Hyprland"
"$mod SHIFT, Q, killactive,"
"$mod, F, fullscreenstate, 2 -1" # dont inform
"$mod SHIFT, F, fullscreenstate, -1 2" # do inform
"$mod, G, togglegroup,"
"$mod SHIFT, N, changegroupactive, f"
"$mod SHIFT, P, changegroupactive, b"
"$mod, T, togglefloating,"
"$mod SHIFT, T, togglesplit,"
"$mod SHIFT, X, pseudo,"
"$mod ALT, ,resizeactive,"
"$mod, Escape, exec, wlogout -p layer-shell"
"$mod, L, exec, ${uwsmSingleApp "hyprlock"}"
"$mod, left, movefocus, l"
"$mod, right, movefocus, r"
"$mod, up, movefocus, u"
"$mod, down, movefocus, d"
"$mod SHIFT, left, movewindow, l"
"$mod SHIFT, right, movewindow, r"
"$mod SHIFT, up, movewindow, u"
"$mod SHIFT, down, movewindow, d"
"$mod ALT, left, movewindoworgroup, l"
"$mod ALT, right, movewindoworgroup, r"
"$mod ALT, up, movewindoworgroup, u"
"$mod ALT, down, movewindoworgroup, d"
"$mod, P, exec, ${pkgs.hyprpicker}/bin/hyprpicker -na"
"CTRL, Print, exec, ${uwsmSingleApp "grimblast"} --notify --cursor copysave output"
"$mod SHIFT CTRL, R, exec, ${uwsmSingleApp "grimblast"} --notify --cursor copysave output"
"ALT, Print, exec, ${uwsmSingleApp "grimblast"} --notify --cursor copysave screen"
"$mod SHIFT ALT, R, exec, ${uwsmSingleApp "grimblast"} --notify --cursor copysave screen"
"$mod, bracketleft, workspace, m-1"
"$mod, bracketright, workspace, m+1"
"$mod SHIFT, bracketleft, focusmonitor, l"
"$mod SHIFT, bracketright, focusmonitor, r"
"$mod SHIFT ALT, bracketleft, movecurrentworkspacetomonitor, l"
"$mod SHIFT ALT, bracketright, movecurrentworkspacetomonitor, r"
]
++ (
# workspaces
# binds $mod + [shift +] {1..10} to [move to] workspace {1..10}
list.concat (list.generate (
x: let
ws = let
c = (x + 1) / 10;
in
builtins.toString (x + 1 - (c * 10));
in [
"$mod, ${ws}, workspace, ${toString (x + 1)}"
"$mod SHIFT, ${ws}, movetoworkspacesilent, ${toString (x + 1)}"
"$mod, F${
if ws == "0"
then "10"
else ws
}, workspace, ${toString (x + 11)}"
"$mod SHIFT, F${
if ws == "0"
then "10"
else ws
}, movetoworkspacesilent, ${toString (x + 11)}"
"$mod ALT, ${ws}, split-workspace, ${toString (x + 1)}"
]
)
10)
);
};
};
}

View file

@ -1,14 +0,0 @@
{
inputs,
pkgs,
...
}: {
programs.hyprlock = {
enable = true;
package = inputs.hyprlock.packages.${pkgs.system}.hyprlock;
settings = {
animations.enabled = false;
};
};
}

View file

@ -1,28 +0,0 @@
{
inputs,
pkgs,
config,
...
}: let
konawallConfig = {
in {
sops.secrets.konawall-py-env = {
sopsFile = ./konawall.yaml;
};
programs.konawall-py = {
enable = true;
settings = {
interval = 30 * 60;
rotate = true;
tags = [
"score:>=100"
"width:>=1500"
];
logging = {
file = "INFO";
console = "DEBUG";
};
};
environmentFile = sops.secrets.konawall-py-env.pathg;
};
}

View file

@ -1,110 +0,0 @@
konawall-py-env: ENC[AES256_GCM,data:8SWQgZkKXffy+GfhbIkZAB3ZJ9a+q5yPmMdt3lgrzezguX23p7vqgRac9AHq1x8=,iv:K5Pj9FuLWbpah8WaD5TZwmomZUgJnuaCdzFlu7K4n/w=,tag:qTlbMlsTeTnXSm+lyDe1iw==,type:str]
sops:
shamir_threshold: 1
age:
- recipient: age1n4kdchmkk3rfkaknxhveqr2ftprdpgwckutt23y6u8639lazzuks77tgav
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSQ2twMTY4UGhEZzNjRG1P
UDhPV1RzcnBwdG9aaVdjV1FxU0dsNzRURVJJCmwvbXRUVFExNjBRb09GTXREZmd4
WS9CclFlbXdhUkNITFI0bW9EVS9YNTQKLS0tIGxPS3JvNEJZSCswYlRZdHJkN2lH
ZHBDblNCN3RmbUtrdTEzVDFQdzI3eDQKY/Q+zAs4cTr2fWDdVqNR+fYRnSIO6s6a
1UOqkFAIZOMmrYMiBu132zgBNT0HU0avvEkZ85Wp72HPv1bUz2QJ4g==
-----END AGE ENCRYPTED FILE-----
- recipient: age1cnu37d5fqyahh9vvc4hj6z6k8ur9ksuefln7sr6g3emmn927eutqxdawuh
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQNUF0NXRNRTAzRzc1ZnUv
cTdmNm8zRTN5WUJ2WUl4aDVmbUNUbzdxd0djCjg3SkF1bmZITW1GNVJ1cHl2QWRP
QitpRHAzNUhWLzNQZUxLeitKQmkyNGsKLS0tIDJkTEVrOS9tZlg1bi9EeXFzSkNz
M2FzNFg4TDc5d0pWOHhUSjJ3Vko2Q0kKDDOhuMe57zE8GSWja37WJrm+dlSROzde
2+RwG6OjDAltWtPpmiLmFCnnGLu3VGYZupbwOtWfBxWiZFQfaYsW9w==
-----END AGE ENCRYPTED FILE-----
- recipient: age1a0m73qr8hhuz8xemv4vymf4wmpghm2hst8wgrn3pn65ext5mf4ksk0vsdm
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBuWmh0Y3hpcXF1RzYvMEJZ
dms2akl4SHBSU1dPaERtM1l5NlJGQjBkc2xnCjM1UEFJZVBSK2ZMaE5GM3lTTlov
RlJxK3kyd0FWYlZncVowd2t1amp2UlEKLS0tIEZwRVVoak90bXVvSlhqenRYMldN
ZDdPOUh0SkFMdDlRV2pIby9ObFZlNXcKleHAiVFw8B6axyOUBhA3nhh+5Q6q82WI
IlOK9nsFJ4yYCU+IZ6TRkAbu7m8xCC24yBOMY3cUZzYc+3HxjIByDw==
-----END AGE ENCRYPTED FILE-----
- recipient: age18hpxz0ghvswv9k30cle73prvnzrsuczqh87jjdk9fl50j3ddndmq9xae0n
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWQ01DWDZtVHpKbFlmREJk
Q2hUdkRUQ1dOWVRaL1NQU3Y1a2NneXpiaVNnClZrZGo5RnIwSk1UbFJ3K1lIZDl3
bmxWUGR2ZTNxaG9aZEhBQlhrQ0g5TUkKLS0tIDM4bHZWTFR2YUZlT3QrSms2SElB
R01tUEJxRy9mQkNlQUloOFk4b0JyOEUKihPiTr07wiT32FBA3KQplBq21EgzyjEA
iXkJDTX5cBn62P53UO/3Gkgi3CG9BjxposrAq5Jmvylej6EgCF13NQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1xgy03g3vjydsxcl0qpdgm8rahjcjq95ucxfwlgr22zwjx3p7jf2s9jk6u5
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxdktCby9jdG4yR0tIZ2JE
N2F2TkRsaXpuOHNXYVBid3NHU21HWFpQOEVFClRIbXVBNm9GMTVyQno5eGNwRkFU
NDhZZDBZT0p1SDh5SW1ycjM2SXZ3R3MKLS0tIGJ2R01TaFFHNnU2cG1wcHA3WkI3
NWxYRDZzZS9Bc25qbW9BUXZaL09rZXMKdpveRhf73CNVCiU+Xjo9TNxW+NTHLJNq
EhYYMnIEtzWDWQOJBzed8+4dpVpjLxJ1Z4EATdRV/vSNLuH+2NENOg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1fv5dafs4n3r5n83qm2hfz7xmnflsz0xf9r3saralrptpgf8mvuxq4t8k3u
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwZUlsZmJZU1JXS1ZxdFNq
emoxdEY3dzZ4ajdWZ1IwTHJhNjZTdUFwR1EwCmo2M3FNaGw0M3phWGFHbThlRnAw
aTFJT3Zkd0RRUTBub3RyTWRhUWl5UTAKLS0tIEpmRlFVeWZILzkzR2hFUG9UbHFS
R0dsOGpPWVJQNkFOd0FHbnBWZ1ZvL1EKsTb8ToKytd5VPig7+koYsMYIKyglIuZm
KvyEgYScynYRiYCjVH92NUo2VaNV+i2g+syUIrcgDvzGa98fgnFITw==
-----END AGE ENCRYPTED FILE-----
- recipient: age120530yclr75k6nrzp6k5jjftj8j4q9v3533guupzk4ct86mjxszqg9e5t5
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1eEN6MS9kVkMySTFpVnNZ
YytlVjJhdUxWQ1I0UkgrWnM0REFUakkvYkJrCkUrRkpXa09rUnByemdJdEljcW10
R01uRkF1WnQ5OTBFOWRuMmtGSkZmT3MKLS0tIFZhNms3blpHWGtJM203Wk5RT1R6
emE2VjJPcnNLTnNNOCtYMFRLd3VuV3cKYdupODU2h9PQN0nXlAkZaaJE+fUNQGmV
TKv6OP8MiWdle50eMvEJCy7sEPTcq02Xwm3cKJCo3k+N2rUPfyf2BQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1c4atxfp05u7zm875s6q8p82ve96rqqpq9smktxlur8pk2yc3qvgql46dp9
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTZHZKcHBOWDZROWc5ZEVS
dW9oT01zR00rUlZOVGhFQXJSS3A4cGZUR21rCkVmUWRvZ3BpMllSdUY4SkNiSDhs
bmt6KzkwWnVObkdJeXV3WWFRdGxlc28KLS0tIDdaNTVSWjNxazhVanA2Mk9QTmlr
cEdOZTlKeWdHREpJQ0VDVlN4eG5LWkEKO9sLRqGxtJUKjeQsvZAodBv1Cvs4z1ut
LptNfGOJQxxwHazKb5VdoXe6Z6qOxciQ1ngNetLC7yEPzEs51smFOg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1rjldv3fn3q686647exmcukthr32gmp6s3axs0lhyenvru9ajp9rs24ukvz
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBveEE2Y0d4RFp2Q1NQV2g3
K1pSSFRNeXlzWlo2U211SzM5Rjg5MG5EUmpRCkhYMVhuS2tONnpVdHJNZ3NGS3kz
Y09KWitzRHIwZnQ4MmR5elZiSGVZdzQKLS0tIFJIcGR1ZTBjSUREeVIvSnlEdzNZ
Q2JJNi9EMG5RMi94WFpncThCdExmM3cKUD+TsPY0T5YilXlpRw4W1cQLeDhOyo1K
TKvcIWq/+vfVa8Smcg2L/9tX5B2uHXDB0UXDpaMfazgsFu4ja7nvSg==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-02-28T21:15:38Z"
mac: ENC[AES256_GCM,data:2QggqmZhRgx+kpvDZOBU/KBLruwxbD4F3NHTiNK2N8Ux133pgLDjP88HDmBy8ZRXmGFdkUK0IqOSx1Axy3qpy14DlSdOw9L/WQhOCybEX21ib+ANb90275FtD+7J8luIvOPbCtus9c9gpqYQIirlQMqwkMZ1QADv62ewmVUJD6w=,iv:4V9KA9oq1TR5+cFtZdEop7haPOavRaRd6wwgJDyJeXQ=,tag:MXwB98KN5kit4Oyl+qQFLw==,type:str]
pgp:
- created_at: "2025-06-27T20:11:04Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA82M54yws73UARAAiUcVShX8Vuf1EW/5Z0OrkBLoMVRaF8FV/CvHmdNZNnIz
K0e0XTyNRSFBwy530VSSgJ5m/db+fQ6SAVEPIJWd22g4yKsHUZOuApQQtdVDQsPB
UG7zKJEtDVDmcMzoKuZx5M/TQhWdGCP1Ut3vYJZ1scDhxuum5RKLzO4bZyHx0NPy
q3U0TRo4RQHtrOGiiBLJnCJhYWqgfGZe3M/Q6VakX5CF0Yy1CmvyCrmHBgjQJ1Br
lMdMpXyTIwkCXOGQYocYOERg1DxcM6eEo4O65tuo0nLG5BExa5Oy5f35O3j73fq9
DHpM7UjSOnsDAuQY0oMpjIaXRPvH/7yBk0hKV1XI9PuC8dDAe25jLvL82UAaMvRC
FKQkLBezYVZB+g8JH0a+ki9ibMk8hpcSQQPaengbiKHROxIXg6L4wZKXs3jFAjVE
xy0NfgLxrBrAXnx0exNl/gokU+LISZ95XgGN6nkjdOllonEOHq78q5kLHwD5KCoy
6qm4Mmv4YdiClRy7NA0lpIRjFeHprj7ZF57tt0vS3yNTaBtVKcUWRwphQvSmcnlF
g5TPWu7x8qQ0gaB5BY+J6oJguqQI7kqWoq1xG2FUWq6klBGumFBWJ/ajd7z3ZyOM
RwUei6PNsXdBcKeQG8dBKK4D0RUakXWjbTyQYHElr0CH06eoNmKcNQlGc4ACrTnS
XgHbkY8kbowDgSx0e7YR4wdtqwgYH7xdcuDyc07iYwL4dWseu8UK5NvSHlXHXvFS
C/h8Z0qOalE1ogzL/gW9kgkfWm7O+EOIm1VqgO1Edv15iFySLTynA6bV9lmzLDw=
=i4jk
-----END PGP MESSAGE-----
fp: CD8CE78CB0B3BDD4
unencrypted_suffix: _unencrypted
version: 3.9.4

View file

@ -1,211 +0,0 @@
_: {
programs.waybar = {
enable = true;
systemd.enable = true;
style = ''
* {
border: none;
border-radius: 0;
font-family: Monaspace Krypton, monospace;
font-size: 13px;
min-height: 0;
}
window#waybar {
all:unset;
}
.modules-left, .modules-right, .modules-center {
background: alpha(@base, 0.9);
box-shadow: 0px 0px 2px rgba(0,0,0,0.6);
color: @text;
padding: 5px;
margin: 2px 4px;
border: 1px solid @lavender;
}
tooltip {
background: rgba(43, 48, 59, 0.5);
border: 1px solid rgba(100, 114, 125, 0.5);
}
tooltip label {
color: white;
}
#workspaces {
border-right: 1px solid @surface2;
}
#workspaces button.persistent {
background: @theme_unfocused_bg_color;
color: @subtext1;
}
#workspaces button {
padding: 2px 5px;
background: @surface0;
border-bottom: 3px solid transparent;
}
#workspaces button.empty {
background: @crust;
color: @subtext1;
}
#workspaces button.visible {
background: @pink;
color: @theme_selected_fg_color;
border-bottom: 3px solid @rosewater;
}
#workspaces button.urgent {
background: @red;
color: @theme_selected_fg_color;
}
#workspaces button.active, #workspaces button.focused {
background: @theme_selected_bg_color;
color: @theme_selected_fg_color;
border-bottom: 3px solid white;
}
#window {
padding: 0 10px;
}
window#waybar.empty #window {
padding: 0px;
margin: 0px;
}
#mode, #clock, #battery, #idle_inhibitor, #tray, #wireplumber, #bluetooth, #backlight, #mpris {
padding: 0 5px;
margin: 0 5px;
}
#mpris {
color: @mantle;
}
#mpris.playing {
background-color: @lavender;
}
#mpris.paused {
background-color: @mauve;
}
#mpris.stopped {
background-color: @rosewater;
}
#mode {
background: #64727D;
border-bottom: 3px solid white;
}
#clock {
}
#battery {
}
#battery.charging {
color: white;
background-color: #26A65B;
}
@keyframes blink {
to {
background-color: #ffffff;
color: black;
}
}
#battery.warning:not(.charging) {
background: #f53c3c;
color: white;
animation-name: blink;
animation-duration: 0.5s;
animation-timing-function: steps(12);
animation-iteration-count: infinite;
animation-direction: alternate;
}
'';
settings.main = {
layer = "top";
position = "top";
mode = "dock";
exclusive = true;
modules-left = [
"hyprland/workspaces"
"hyprland/submap"
"hyprland/window"
];
modules-center = [
"clock"
"mpris"
];
modules-right = [
"privacy"
"bluetooth"
"wireplumber"
"idle_inhibitor"
"power-profiles-daemon"
"backlight"
"battery"
"tray"
];
idle_inhibitor = {
format = "idin {icon}";
format-icons = {
activated = "active";
deactivated = "inactive";
};
};
bluetooth = {
on-click = "blueman-manager";
format = "bt {status}";
format-connected-battery = "bt {device_alias} {device_battery_percentage}%";
format-connected = "bt {num_connections} connected";
tooltip-format = "{controller_alias}\t{controller_address}\n\n{num_connections} connected";
tooltip-format-connected = "{controller_alias}\t{controller_address}\n\n{num_connections} connected\n\n{device_enumerate}";
tooltip-format-enumerate-connected = "{device_alias}\t{device_address}";
tooltip-format-enumerate-connected-battery = "{device_alias}\t{device_address}\t{device_battery_percentage}%";
};
wireplumber = {
format = "vol {volume}%";
max-volume = 150;
};
backlight = {
format = "bl {percent}%";
};
battery = {
format = "bat {capacity}%";
format-tooltip = "{power}W, {timeTo}, {health}%";
interval = 60;
states = {
warning = 30;
critical = 15;
};
};
tray = {
spacing = 4;
};
clock = {
format = "{:%F %H:%M %Z}";
interval = 60;
};
};
};
}

View file

@ -1,5 +0,0 @@
_: {
programs.wlogout = {
enable = true;
};
}

View file

@ -1,12 +0,0 @@
_: {
programs.wofi = {
enable = true;
settings = {
insensitive = true;
allow_images = true;
hide_scroll = true;
mode = "dmenu";
prompt = "";
};
};
}

View file

@ -1,14 +0,0 @@
_: {
xdg = {
enable = true;
autostart.enable = true;
mime.enable = true;
mimeApps = {
enable = true;
defaultApplications = {
"inode/directory" = "pcmanfm.desktop";
};
};
};
}

View file

@ -1,223 +0,0 @@
local _dir_ = debug.getinfo(1, "S").source:sub(2):match("(.*[/\\])") or "./"
package.path = _dir_ .. "?.lua"
kat = require("kat")
liluat = require("liluat")
ftcsv = require("ftcsv")
function tpl(t)
local ct = liluat.compile(t, { start_tag = "{%", end_tag = "%}" })
return function(values)
return liluat.render(ct, values)
end
end
function string.split(inputstr, sep)
if sep == nil then
sep = "%s"
end
local t = {}
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
table.insert(t, str)
end
return t
end
components = {}
local base_font = "Monaspace Krypton"
local formats = {
h1 = string.format("%s:bold:size=16", base_font),
font = "${font %s}%s$font",
item = "${color grey}%s:$color",
}
local font_formats = {
h1 = "not_nil",
}
function conky_fmt(trigger, ...)
text = table.concat({...}, " ")
if font_formats[trigger] ~= nil then
return conky_parse(string.format(formats.font, formats[trigger], text))
else
return conky_parse(string.format(formats[trigger], text))
end
end
function cpu_model()
return string.format([=[${execi %i grep model /proc/cpuinfo | cut -d : -f2 | tail -1 | sed 's/\s//' | sed 's/ [[:digit:]]*-Core Processor$//g'}]=], kat.exec_interval)
end
function cpu_sct()
return string.format("${execi %i %scpu_sct.sh}", kat.exec_interval, kat.root_dir)
end
function conky_mem_section()
local mem_tpl = tpl([[
${lua fmt h1 RAM} ${hr}
${color grey}Usage:$color $mem/$memmax - $memperc% ${membar 4}
${color grey}Easy-to-free:$color ${memeasyfree}
]])
end
function conky_storage_section()
end
function conky_cpu_section()
local cpu_tpl = tpl([[
${lua fmt h1 CPU} ${hr}
${color grey}Variety:$color {%= cpu_model() %} {%= cpu_sct() %}
${cpugraph}
${color grey}Frequency:$color ${freq_g} GHz
${color grey}Usage:$color $cpu% ${cpubar 4}
]])
return conky_parse(cpu_tpl({ cpu_model = cpu_model, cpu_sct = cpu_sct }))
end
function gpu_query(query)
return string.format([[${execi %i nvidia-smi --query-gpu=%s --format=csv,noheader | sed 's/\d*\s\%%//' }]], 15, query)
end
-- GPU Query
local query_headers = {
"index",
"name",
"driver_version",
"fan.speed",
"utilization.gpu",
"utilization.memory",
"memory.used",
"clocks.current.graphics",
"clocks.current.memory",
"temperature.gpu",
"clocks.current.sm",
"clocks.current.video",
"memory.total",
"utilization.encoder",
"utilization.decoder",
}
local gpu_display_templates = {
index = "${lua fmt h1 GPU %s} ${hr}",
default = "${lua fmt item %s} %s",
hasbar = "${lua fmt item %s} %s ${nvidiabar %s %s}",
}
local gpu_header_aliases = {
["name"] = "Card",
["driver_version"] = "Driver Version",
["fan.speed"] = "Fan Speed",
["utilization.gpu"] = "Core Usage",
["utilization.memory"] = "Memory Usage",
["utilization.encoder"] = "Encoder Usage",
["utilization.decoder"] = "Decoder Usage",
["clocks.current.graphics"] = "Core Frequency",
["clocks.current.sm"] = "SM Frequency",
["clocks.current.memory"] = "Memory Frequency",
["clocks.current.video"] = "Video Frequency",
["memory.used"] = "Memory Used",
["memory.total"] = "Memory Total",
["temperature.gpu"] = "Temperature",
};
local gpu_header_to_nvidiabar = {
--[[["fan.speed"] = "fanlevel",
["utilization.gpu"] = "gpuutil",
["utilization.memory"] = "memutil",
["clocks.current.graphics"] = "gpufreq",
["clocks.current.memory"] = "memfreq",
["temperature.gpu"] = "temp",
["memory.used"] = "mem",]]--
};
-- Reverse index
local query_headers_index = {}
for i, header in ipairs(query_headers) do
query_headers_index[header] = i
end
-- Command generation caching
local query_header_string = table.concat(query_headers, ",")
local query_command = string.format("nvidia-smi --query-gpu=%s --format=csv,nounits", query_header_string)
local headers = nil
function gpu_csv_query()
local gpus = {}
local query_ran = io.popen(query_command)
local query = query_ran:read("*all")
local query = query:gsub(",%s", ",")
local items, raw_headers = ftcsv.parse(query, {
loadFromString = true,
})
if headers == nil then
headers = {}
for i, heading in ipairs(raw_headers) do
local heading_split = string.split(heading)
local query_unit
local key = heading_split[1]
-- if the heading does not have a [unit] section
if #heading_split == 1 then
-- use a table to define what the key's unit should be
local keys_to_units = {
["temperature.gpu"] = "°C",
index = nil,
driver_version = nil,
name = nil,
}
-- give it a unit
query_unit = keys_to_units[key]
else
query_unit = string.sub(heading_split[2], 2, -2)
local unit_remap = {
MiB = " MiB"
}
if unit_remap[query_unit] ~= nil then
query_unit = unit_remap[query_unit]
end
end
headers[heading] = {
clean = key,
unit = query_unit
}
end
end
for i, gpu in pairs(items) do
current_gpu = {}
for header, data in pairs(gpu) do
local cur_header = headers[header]
local subformat = "%s%s"
local unit = cur_header.unit or ""
data_sf = string.format(subformat, data, unit)
local display_idx = query_headers_index[cur_header.clean] or 500
if gpu_display_templates[cur_header.clean] ~= nil then
display = string.format(gpu_display_templates[cur_header.clean], data_sf)
else
if gpu_header_to_nvidiabar[cur_header.clean] ~= nil then
local nvidiabar = gpu_header_to_nvidiabar[cur_header.clean]
display = string.format(gpu_display_templates.hasbar, gpu_header_aliases[cur_header.clean], data_sf, nvidiabar, i)
else
display = string.format(gpu_display_templates.default, gpu_header_aliases[cur_header.clean], data_sf)
end
end
current_gpu[display_idx] = display
end
gpus[i] = current_gpu
end
return gpus
end
-- GPU Display
function conky_gpu_section()
gpus = gpu_csv_query()
local text = ""
for idx, gpu in pairs(gpus) do
for i=1,#gpu do
text = text .. string.format("%s\n", gpu[i])
end
end
return conky_parse(text)
end
return components

View file

@ -1,75 +0,0 @@
local _dir_ = debug.getinfo(1, "S").source:sub(2):match("(.*[/\\])") or "./"
package.path = _dir_ .. "?.lua"
kat = require("kat")
conky.config = {
alignment = 'top_left',
background = false,
border_width = 1,
cpu_avg_samples = 2,
default_color = 'white',
default_outline_color = 'white',
default_shade_color = 'white',
default_graph_height = 60,
double_buffer = true,
draw_borders = false,
draw_graph_borders = true,
draw_outline = false,
draw_shades = false,
extra_newline = false,
font = 'Monaspace Krypton:size=12',
gap_x = 60,
gap_y = 60,
minimum_height = 5,
minimum_width = 5,
net_avg_samples = 2,
no_buffers = true,
out_to_console = false,
out_to_ncurses = false,
out_to_stderr = false,
out_to_wayland = true,
out_to_x = false,
own_window = true,
own_window_class = 'Conky',
own_window_type = 'override',
-- own_window_transparent = true,
own_window_colour = "000000",
own_window_argb_visual = true,
own_window_argb_value = 153,
own_window_hints = 'undecorated,sticky,below,skip_taskbar,skip_pager',
show_graph_range = false,
show_graph_scale = false,
stippled_borders = 0,
update_interval = 1.0,
uppercase = false,
use_spacer = 'none',
use_xft = true,
lua_load = _dir_ .. "components.lua",
}
conky.text = [[
$sysname $nodename $kernel $machine
$hr
${color grey}Uptime:$color $uptime
${color grey}Frequency:$color $freq_g GHz
${color grey}RAM Usage:$color $mem/$memmax - $memperc% ${membar 4}
${color grey}Swap Usage:$color $swap/$swapmax - $swapperc% ${swapbar 4}
${color grey}CPU Usage:$color $cpu% ${cpubar 4}
${color grey}Processes:$color $processes ${color grey}Running:$color $running_processes
$hr
${color grey}File systems:
/ $color${fs_used /}/${fs_size /} ${fs_bar 6 /}
${color grey}Networking:
Up:$color ${upspeed} ${color grey} - Down:$color ${downspeed}
$hr
${color grey}Name PID CPU% MEM%
${color lightgrey} ${top name 1} ${top pid 1} ${top cpu 1} ${top mem 1}
${color lightgrey} ${top name 2} ${top pid 2} ${top cpu 2} ${top mem 2}
${color lightgrey} ${top name 3} ${top pid 3} ${top cpu 3} ${top mem 3}
${color lightgrey} ${top name 4} ${top pid 4} ${top cpu 4} ${top mem 4}
${lua cpu_section}
${lua gpu_section}
]]

View file

@ -1,30 +0,0 @@
{ config, pkgs, ... }: {
home.packages = with pkgs; [
jq
];
xdg.configFile.conky = {
recursive = true;
source = config.lib.file.mkOutOfStoreSymlink ./.;
};
systemd.user.services.conky = {
Unit = {
Description = "Conky - Lightweight system monitor";
After = [ "graphical-session.target" ];
X-Restart-Triggers = [
./conky.conf
];
};
Service = {
Restart = "always";
RestartSec = "3";
ExecStartPre = "${pkgs.coreutils}/bin/sleep 5";
ExecStart = toString ([ "${(pkgs.conky.override { nvidiaSupport = true; })}/bin/conky"]);
};
Install.WantedBy = [ "graphical-session.target" ];
};
}

View file

@ -1,12 +0,0 @@
#!/usr/bin/env bash
CPU_JSON=$(lscpu --json | jq '.lscpu | reduce .[] as $i ({}; .[$i.field] = $i.data)')
CPU_SOCKETS=$(echo "$CPU_JSON" | jq '."Socket(s):"' -r)
CPU_CORES_PER_SOCKET=$(echo "$CPU_JSON" | jq '."Core(s) per socket:"' -r)
CPU_THREADS_PER_CORE=$(echo "$CPU_JSON" | jq '."Thread(s) per core:"' -r)
CPU_TOTAL_THREADS_PER_SOCKET=$(($CPU_CORES_PER_SOCKET*$CPU_THREADS_PER_CORE))
if [ $CPU_SOCKETS -eq 1 ]; then
echo "${CPU_CORES_PER_SOCKET}c${CPU_TOTAL_THREADS_PER_SOCKET}t"
else
echo "${CPU_SOCKETS}s${CPU_CORES_PER_SOCKET}t${CPU_TOTAL_THREADS_PER_SOCKET}t"
fi

View file

@ -1,819 +0,0 @@
local ftcsv = {
_VERSION = 'ftcsv 1.4.0',
_DESCRIPTION = 'CSV library for Lua',
_URL = 'https://github.com/FourierTransformer/ftcsv',
_LICENSE = [[
The MIT License (MIT)
Copyright (c) 2016-2023 Shakil Thakur
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]
}
-- perf
local sbyte = string.byte
local ssub = string.sub
-- luajit/lua compatability layer
local luaCompatibility = {}
if type(jit) == 'table' or _ENV then
-- luajit and lua 5.2+
luaCompatibility.load = _G.load
else
-- lua 5.1
luaCompatibility.load = loadstring
end
-- luajit specific speedups
-- luajit performs faster with iterating over string.byte,
-- whereas vanilla lua performs faster with string.find
if type(jit) == 'table' then
luaCompatibility.LuaJIT = true
-- finds the end of an escape sequence
function luaCompatibility.findClosingQuote(i, inputLength, inputString, quote, doubleQuoteEscape)
local currentChar, nextChar = sbyte(inputString, i), nil
while i <= inputLength do
nextChar = sbyte(inputString, i+1)
-- this one deals with " double quotes that are escaped "" within single quotes "
-- these should be turned into a single quote at the end of the field
if currentChar == quote and nextChar == quote then
doubleQuoteEscape = true
i = i + 2
currentChar = sbyte(inputString, i)
-- identifies the escape toggle
elseif currentChar == quote and nextChar ~= quote then
return i-1, doubleQuoteEscape
else
i = i + 1
currentChar = nextChar
end
end
end
else
luaCompatibility.LuaJIT = false
-- vanilla lua closing quote finder
function luaCompatibility.findClosingQuote(i, inputLength, inputString, quote, doubleQuoteEscape)
local j, difference
i, j = inputString:find('"+', i)
if j == nil then
return nil
end
difference = j - i
if difference >= 1 then doubleQuoteEscape = true end
if difference % 2 == 1 then
return luaCompatibility.findClosingQuote(j+1, inputLength, inputString, quote, doubleQuoteEscape)
end
return j-1, doubleQuoteEscape
end
end
-- determine the real headers as opposed to the header mapping
local function determineRealHeaders(headerField, fieldsToKeep)
local realHeaders = {}
local headerSet = {}
for i = 1, #headerField do
if not headerSet[headerField[i]] then
if fieldsToKeep ~= nil and fieldsToKeep[headerField[i]] then
table.insert(realHeaders, headerField[i])
headerSet[headerField[i]] = true
elseif fieldsToKeep == nil then
table.insert(realHeaders, headerField[i])
headerSet[headerField[i]] = true
end
end
end
return realHeaders
end
local function determineTotalColumnCount(headerField, fieldsToKeep)
local totalColumnCount = 0
local headerFieldSet = {}
for _, header in pairs(headerField) do
-- count unique columns and
-- also figure out if it's a field to keep
if not headerFieldSet[header] and
(fieldsToKeep == nil or fieldsToKeep[header]) then
headerFieldSet[header] = true
totalColumnCount = totalColumnCount + 1
end
end
return totalColumnCount
end
local function generateHeadersMetamethod(finalHeaders)
-- if a header field tries to escape, we will simply return nil
-- the parser will still parse, but wont get the performance benefit of
-- having headers predefined
for _, headers in ipairs(finalHeaders) do
if headers:find("]") then
return nil
end
end
local rawSetup = "local t, k, _ = ... \
rawset(t, k, {[ [[%s]] ]=true})"
rawSetup = rawSetup:format(table.concat(finalHeaders, "]] ]=true, [ [["))
return luaCompatibility.load(rawSetup)
end
-- main function used to parse
local function parseString(inputString, i, options)
-- keep track of my chars!
local inputLength = options.inputLength or #inputString
local currentChar, nextChar = sbyte(inputString, i), nil
local skipChar = 0
local field
local fieldStart = i
local fieldNum = 1
local lineNum = 1
local lineStart = i
local doubleQuoteEscape, emptyIdentified = false, false
local skipIndex
local charPatternToSkip = "[" .. options.delimiter .. "\r\n]"
--bytes
local CR = sbyte("\r")
local LF = sbyte("\n")
local quote = sbyte('"')
local delimiterByte = sbyte(options.delimiter)
-- explode most used options
local headersMetamethod = options.headersMetamethod
local fieldsToKeep = options.fieldsToKeep
local ignoreQuotes = options.ignoreQuotes
local headerField = options.headerField
local endOfFile = options.endOfFile
local buffered = options.buffered
local outResults = {}
-- in the first run, the headers haven't been set yet.
if headerField == nil then
headerField = {}
-- setup a metatable to simply return the key that's passed in
local headerMeta = {__index = function(_, key) return key end}
setmetatable(headerField, headerMeta)
end
if headersMetamethod then
setmetatable(outResults, {__newindex = headersMetamethod})
end
outResults[1] = {}
-- totalColumnCount based on unique headers and fieldsToKeep
local totalColumnCount = options.totalColumnCount or determineTotalColumnCount(headerField, fieldsToKeep)
local function assignValueToField()
if fieldsToKeep == nil or fieldsToKeep[headerField[fieldNum]] then
-- create new field
if ignoreQuotes == false and sbyte(inputString, i-1) == quote then
field = ssub(inputString, fieldStart, i-2)
else
field = ssub(inputString, fieldStart, i-1)
end
if doubleQuoteEscape then
field = field:gsub('""', '"')
end
-- reset flags
doubleQuoteEscape = false
emptyIdentified = false
-- assign field in output
if headerField[fieldNum] ~= nil then
outResults[lineNum][headerField[fieldNum]] = field
else
error('ftcsv: too many columns in row ' .. options.rowOffset + lineNum)
end
end
end
while i <= inputLength do
-- go by two chars at a time,
-- currentChar is set at the bottom.
nextChar = sbyte(inputString, i+1)
-- empty string
if ignoreQuotes == false and currentChar == quote and nextChar == quote then
skipChar = 1
fieldStart = i + 2
emptyIdentified = true
-- escape toggle.
-- This can only happen if fields have quotes around them
-- so the current "start" has to be where a quote character is.
elseif ignoreQuotes == false and currentChar == quote and nextChar ~= quote and fieldStart == i then
fieldStart = i + 1
-- if an empty field was identified before assignment, it means
-- that this is a quoted field that starts with escaped quotes
-- ex: """a"""
if emptyIdentified then
fieldStart = fieldStart - 2
emptyIdentified = false
end
skipChar = 1
i, doubleQuoteEscape = luaCompatibility.findClosingQuote(i+1, inputLength, inputString, quote, doubleQuoteEscape)
-- create some fields
elseif currentChar == delimiterByte then
assignValueToField()
-- increaseFieldIndices
fieldNum = fieldNum + 1
fieldStart = i + 1
-- newline
elseif (currentChar == LF or currentChar == CR) then
assignValueToField()
-- handle CRLF
if (currentChar == CR and nextChar == LF) then
skipChar = 1
fieldStart = fieldStart + 1
end
-- incrememnt for new line
if fieldNum < totalColumnCount then
-- sometimes in buffered mode, the buffer starts with a newline
-- this skips the newline and lets the parsing continue.
if buffered and lineNum == 1 and fieldNum == 1 and field == "" then
fieldStart = i + 1 + skipChar
lineStart = fieldStart
else
error('ftcsv: too few columns in row ' .. options.rowOffset + lineNum)
end
else
lineNum = lineNum + 1
outResults[lineNum] = {}
fieldNum = 1
fieldStart = i + 1 + skipChar
lineStart = fieldStart
end
elseif luaCompatibility.LuaJIT == false then
skipIndex = inputString:find(charPatternToSkip, i)
if skipIndex then
skipChar = skipIndex - i - 1
end
end
-- in buffered mode and it can't find the closing quote
-- it usually means in the middle of a buffer and need to backtrack
if i == nil then
if buffered then
outResults[lineNum] = nil
return outResults, lineStart
else
error("ftcsv: can't find closing quote in row " .. options.rowOffset + lineNum ..
". Try running with the option ignoreQuotes=true if the source incorrectly uses quotes.")
end
end
-- Increment Counter
i = i + 1 + skipChar
if (skipChar > 0) then
currentChar = sbyte(inputString, i)
else
currentChar = nextChar
end
skipChar = 0
end
if buffered and not endOfFile then
outResults[lineNum] = nil
return outResults, lineStart
end
-- create last new field
assignValueToField()
-- remove last field if empty
if fieldNum < totalColumnCount then
-- indicates last field was really just a CRLF,
-- so, it can be removed
if fieldNum == 1 and field == "" then
outResults[lineNum] = nil
else
error('ftcsv: too few columns in row ' .. options.rowOffset + lineNum)
end
end
return outResults, i, totalColumnCount
end
local function handleHeaders(headerField, options)
-- for files where there aren't headers!
if options.headers == false then
for j = 1, #headerField do
headerField[j] = j
end
else
-- make sure a header isn't empty if there are headers
for _, headerName in ipairs(headerField) do
if #headerName == 0 then
error('ftcsv: Cannot parse a file which contains empty headers')
end
end
end
-- rename fields as needed!
if options.rename then
-- basic rename (["a" = "apple"])
for j = 1, #headerField do
if options.rename[headerField[j]] then
headerField[j] = options.rename[headerField[j]]
end
end
-- files without headers, but with a options.rename need to be handled too!
if #options.rename > 0 then
for j = 1, #options.rename do
headerField[j] = options.rename[j]
end
end
end
-- apply some sweet header manipulation
if options.headerFunc then
for j = 1, #headerField do
headerField[j] = options.headerFunc(headerField[j])
end
end
return headerField
end
-- load an entire file into memory
local function loadFile(textFile, amount)
local file = io.open(textFile, "r")
if not file then error("ftcsv: File not found at " .. textFile) end
local lines = file:read(amount)
if amount == "*all" then
file:close()
end
return lines, file
end
local function initializeInputFromStringOrFile(inputFile, options, amount)
-- handle input via string or file!
local inputString, file
if options.loadFromString then
inputString = inputFile
else
inputString, file = loadFile(inputFile, amount)
end
-- if they sent in an empty file...
if inputString == "" then
error('ftcsv: Cannot parse an empty file')
end
return inputString, file
end
local function determineArgumentOrder(delimiter, options)
-- backwards compatibile layer
if type(delimiter) == "string" then
return delimiter, options
-- the new format for parseLine
elseif type(delimiter) == "table" then
local realDelimiter = delimiter.delimiter or ","
return realDelimiter, delimiter
-- if nothing is specified, assume "," delimited and call it a day!
else
return ",", nil
end
end
local function parseOptions(delimiter, options, fromParseLine)
-- delimiter MUST be one character
assert(#delimiter == 1 and type(delimiter) == "string", "the delimiter must be of string type and exactly one character")
local fieldsToKeep = nil
if options then
if options.headers ~= nil then
assert(type(options.headers) == "boolean", "ftcsv only takes the boolean 'true' or 'false' for the optional parameter 'headers' (default 'true'). You passed in '" .. tostring(options.headers) .. "' of type '" .. type(options.headers) .. "'.")
end
if options.rename ~= nil then
assert(type(options.rename) == "table", "ftcsv only takes in a key-value table for the optional parameter 'rename'. You passed in '" .. tostring(options.rename) .. "' of type '" .. type(options.rename) .. "'.")
end
if options.fieldsToKeep ~= nil then
assert(type(options.fieldsToKeep) == "table", "ftcsv only takes in a list (as a table) for the optional parameter 'fieldsToKeep'. You passed in '" .. tostring(options.fieldsToKeep) .. "' of type '" .. type(options.fieldsToKeep) .. "'.")
local ofieldsToKeep = options.fieldsToKeep
if ofieldsToKeep ~= nil then
fieldsToKeep = {}
for j = 1, #ofieldsToKeep do
fieldsToKeep[ofieldsToKeep[j]] = true
end
end
if options.headers == false and options.rename == nil then
error("ftcsv: fieldsToKeep only works with header-less files when using the 'rename' functionality")
end
end
if options.loadFromString ~= nil then
assert(type(options.loadFromString) == "boolean", "ftcsv only takes a boolean value for optional parameter 'loadFromString'. You passed in '" .. tostring(options.loadFromString) .. "' of type '" .. type(options.loadFromString) .. "'.")
end
if options.headerFunc ~= nil then
assert(type(options.headerFunc) == "function", "ftcsv only takes a function value for optional parameter 'headerFunc'. You passed in '" .. tostring(options.headerFunc) .. "' of type '" .. type(options.headerFunc) .. "'.")
end
if options.ignoreQuotes == nil then
options.ignoreQuotes = false
else
assert(type(options.ignoreQuotes) == "boolean", "ftcsv only takes a boolean value for optional parameter 'ignoreQuotes'. You passed in '" .. tostring(options.ignoreQuotes) .. "' of type '" .. type(options.ignoreQuotes) .. "'.")
end
if fromParseLine == true then
if options.bufferSize == nil then
options.bufferSize = 2^16
else
assert(type(options.bufferSize) == "number", "ftcsv only takes a number value for optional parameter 'bufferSize'. You passed in '" .. tostring(options.bufferSize) .. "' of type '" .. type(options.bufferSize) .. "'.")
end
else
if options.bufferSize ~= nil then
error("ftcsv: bufferSize can only be specified using 'parseLine'. When using 'parse', the entire file is read into memory")
end
end
else
options = {
["headers"] = true,
["loadFromString"] = false,
["ignoreQuotes"] = false,
["bufferSize"] = 2^16
}
end
return options, fieldsToKeep
end
local function findEndOfHeaders(str, entireFile)
local i = 1
local quote = sbyte('"')
local newlines = {
[sbyte("\n")] = true,
[sbyte("\r")] = true
}
local quoted = false
local char = sbyte(str, i)
repeat
-- this should still work for escaped quotes
-- ex: " a "" b \r\n " -- there is always a pair around the newline
if char == quote then
quoted = not quoted
end
i = i + 1
char = sbyte(str, i)
until (newlines[char] and not quoted) or char == nil
if not entireFile and char == nil then
error("ftcsv: bufferSize needs to be larger to parse this file")
end
local nextChar = sbyte(str, i+1)
if nextChar == sbyte("\n") and char == sbyte("\r") then
i = i + 1
end
return i
end
local function determineBOMOffset(inputString)
-- BOM files start with bytes 239, 187, 191
if sbyte(inputString, 1) == 239
and sbyte(inputString, 2) == 187
and sbyte(inputString, 3) == 191 then
return 4
else
return 1
end
end
local function parseHeadersAndSetupArgs(inputString, delimiter, options, fieldsToKeep, entireFile)
local startLine = determineBOMOffset(inputString)
local endOfHeaderRow = findEndOfHeaders(inputString, entireFile)
local parserArgs = {
delimiter = delimiter,
headerField = nil,
fieldsToKeep = nil,
inputLength = endOfHeaderRow,
buffered = false,
ignoreQuotes = options.ignoreQuotes,
rowOffset = 0
}
local rawHeaders, endOfHeaders = parseString(inputString, startLine, parserArgs)
-- manipulate the headers as per the options
local modifiedHeaders = handleHeaders(rawHeaders[1], options)
parserArgs.headerField = modifiedHeaders
parserArgs.fieldsToKeep = fieldsToKeep
parserArgs.inputLength = nil
if options.headers == false then endOfHeaders = startLine end
local finalHeaders = determineRealHeaders(modifiedHeaders, fieldsToKeep)
if options.headers ~= false then
local headersMetamethod = generateHeadersMetamethod(finalHeaders)
parserArgs.headersMetamethod = headersMetamethod
end
return endOfHeaders, parserArgs, finalHeaders
end
-- runs the show!
function ftcsv.parse(inputFile, delimiter, options)
local delimiter, options = determineArgumentOrder(delimiter, options)
local options, fieldsToKeep = parseOptions(delimiter, options, false)
local inputString = initializeInputFromStringOrFile(inputFile, options, "*all")
local endOfHeaders, parserArgs, finalHeaders = parseHeadersAndSetupArgs(inputString, delimiter, options, fieldsToKeep, true)
local output = parseString(inputString, endOfHeaders, parserArgs)
return output, finalHeaders
end
local function getFileSize (file)
local current = file:seek()
local size = file:seek("end")
file:seek("set", current)
return size
end
local function determineAtEndOfFile(file, fileSize)
if file:seek() >= fileSize then
return true
else
return false
end
end
local function initializeInputFile(inputString, options)
if options.loadFromString == true then
error("ftcsv: parseLine currently doesn't support loading from string")
end
return initializeInputFromStringOrFile(inputString, options, options.bufferSize)
end
function ftcsv.parseLine(inputFile, delimiter, userOptions)
local delimiter, userOptions = determineArgumentOrder(delimiter, userOptions)
local options, fieldsToKeep = parseOptions(delimiter, userOptions, true)
local inputString, file = initializeInputFile(inputFile, options)
local fileSize, atEndOfFile = 0, false
fileSize = getFileSize(file)
atEndOfFile = determineAtEndOfFile(file, fileSize)
local endOfHeaders, parserArgs, _ = parseHeadersAndSetupArgs(inputString, delimiter, options, fieldsToKeep, atEndOfFile)
parserArgs.buffered = true
parserArgs.endOfFile = atEndOfFile
local parsedBuffer, endOfParsedInput, totalColumnCount = parseString(inputString, endOfHeaders, parserArgs)
parserArgs.totalColumnCount = totalColumnCount
inputString = ssub(inputString, endOfParsedInput)
local bufferIndex, returnedRowsCount = 0, 0
local currentRow, buffer
return function()
-- check parsed buffer for value
bufferIndex = bufferIndex + 1
currentRow = parsedBuffer[bufferIndex]
if currentRow then
returnedRowsCount = returnedRowsCount + 1
return returnedRowsCount, currentRow
end
-- read more of the input
buffer = file:read(options.bufferSize)
if not buffer then
file:close()
return nil
else
parserArgs.endOfFile = determineAtEndOfFile(file, fileSize)
end
-- appends the new input to what was left over
inputString = inputString .. buffer
-- re-analyze and load buffer
parserArgs.rowOffset = returnedRowsCount
parsedBuffer, endOfParsedInput = parseString(inputString, 1, parserArgs)
bufferIndex = 1
-- cut the input string down
inputString = ssub(inputString, endOfParsedInput)
if #parsedBuffer == 0 then
error("ftcsv: bufferSize needs to be larger to parse this file")
end
returnedRowsCount = returnedRowsCount + 1
return returnedRowsCount, parsedBuffer[bufferIndex]
end
end
-- The ENCODER code is below here
-- This could be broken out, but is kept here for portability
local function delimitField(field)
field = tostring(field)
if field:find('"') then
return field:gsub('"', '""')
else
return field
end
end
local function generateDelimitAndQuoteField(delimiter)
local generatedFunction = function(field)
field = tostring(field)
if field:find('"') then
return '"' .. field:gsub('"', '""') .. '"'
elseif field:find('[\n' .. delimiter .. ']') then
return '"' .. field .. '"'
else
return field
end
end
return generatedFunction
end
local function escapeHeadersForLuaGenerator(headers)
local escapedHeaders = {}
for i = 1, #headers do
if headers[i]:find('"') then
escapedHeaders[i] = headers[i]:gsub('"', '\\"')
else
escapedHeaders[i] = headers[i]
end
end
return escapedHeaders
end
-- a function that compiles some lua code to quickly print out the csv
local function csvLineGenerator(inputTable, delimiter, headers, options)
local escapedHeaders = escapeHeadersForLuaGenerator(headers)
local outputFunc = [[
local args, i = ...
i = i + 1;
if i > ]] .. #inputTable .. [[ then return nil end;
return i, '"' .. args.delimitField(args.t[i]["]] ..
table.concat(escapedHeaders, [["]) .. '"]] ..
delimiter .. [["' .. args.delimitField(args.t[i]["]]) ..
[["]) .. '"\r\n']]
if options and options.onlyRequiredQuotes == true then
outputFunc = [[
local args, i = ...
i = i + 1;
if i > ]] .. #inputTable .. [[ then return nil end;
return i, args.delimitField(args.t[i]["]] ..
table.concat(escapedHeaders, [["]) .. ']] ..
delimiter .. [[' .. args.delimitField(args.t[i]["]]) ..
[["]) .. '\r\n']]
end
local arguments = {}
arguments.t = inputTable
-- we want to use the same delimitField throughout,
-- so we're just going to pass it in
if options and options.onlyRequiredQuotes == true then
arguments.delimitField = generateDelimitAndQuoteField(delimiter)
else
arguments.delimitField = delimitField
end
return luaCompatibility.load(outputFunc), arguments, 0
end
local function validateHeaders(headers, inputTable)
for i = 1, #headers do
if inputTable[1][headers[i]] == nil then
error("ftcsv: the field '" .. headers[i] .. "' doesn't exist in the inputTable")
end
end
end
local function initializeOutputWithEscapedHeaders(escapedHeaders, delimiter, options)
local output = {}
if options and options.onlyRequiredQuotes == true then
output[1] = table.concat(escapedHeaders, delimiter) .. '\r\n'
else
output[1] = '"' .. table.concat(escapedHeaders, '"' .. delimiter .. '"') .. '"\r\n'
end
return output
end
local function escapeHeadersForOutput(headers, delimiter, options)
local escapedHeaders = {}
local delimitField = delimitField
if options and options.onlyRequiredQuotes == true then
delimitField = generateDelimitAndQuoteField(delimiter)
end
for i = 1, #headers do
escapedHeaders[i] = delimitField(headers[i])
end
return escapedHeaders
end
local function extractHeadersFromTable(inputTable)
local headers = {}
for key, _ in pairs(inputTable[1]) do
headers[#headers+1] = key
end
-- lets make the headers alphabetical
table.sort(headers)
return headers
end
local function getHeadersFromOptions(options)
local headers = nil
if options then
if options.fieldsToKeep ~= nil then
assert(
type(options.fieldsToKeep) == "table", "ftcsv only takes in a list (as a table) for the optional parameter 'fieldsToKeep'. You passed in '" .. tostring(options.headers) .. "' of type '" .. type(options.headers) .. "'.")
headers = options.fieldsToKeep
end
end
return headers
end
local function initializeGenerator(inputTable, delimiter, options)
-- delimiter MUST be one character
assert(#delimiter == 1 and type(delimiter) == "string", "the delimiter must be of string type and exactly one character")
local headers = getHeadersFromOptions(options)
if headers == nil then
headers = extractHeadersFromTable(inputTable)
end
validateHeaders(headers, inputTable)
local escapedHeaders = escapeHeadersForOutput(headers, delimiter, options)
local output = initializeOutputWithEscapedHeaders(escapedHeaders, delimiter, options)
return output, headers
end
-- works really quickly with luajit-2.1, because table.concat life
function ftcsv.encode(inputTable, delimiter, options)
local delimiter, options = determineArgumentOrder(delimiter, options)
local output, headers = initializeGenerator(inputTable, delimiter, options)
for i, line in csvLineGenerator(inputTable, delimiter, headers, options) do
output[i+1] = line
end
-- combine and return final string
return table.concat(output)
end
return ftcsv

View file

@ -1,5 +0,0 @@
local _dir_ = debug.getinfo(1, "S").source:sub(2):match("(.*[/\\])") or "./"
kat = { root_dir = _dir_, exec_interval = 3600 }
return kat

View file

@ -1,532 +0,0 @@
--[[
-- liluat - Lightweight Lua Template engine
--
-- Project page: https://github.com/FSMaxB/liluat
--
-- liluat is based on slt2 by henix, see https://github.com/henix/slt2
--
-- Copyright © 2016 Max Bruckner
-- Copyright © 2011-2016 henix
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is furnished
-- to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-- IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--]]
local liluat = {
private = {} --used to expose private functions for testing
}
-- print the current version
liluat.version = function ()
return "1.2.0"
end
-- returns a string containing the fist line until the last line
local function string_lines(lines, first, last)
-- allow negative line numbers
first = (first >= 1) and first or 1
local start_position
local current_position = 1
local line_counter = 1
repeat
if line_counter == first then
start_position = current_position
end
current_position = lines:find('\n', current_position + 1, true)
line_counter = line_counter + 1
until (line_counter == (last + 1)) or (not current_position)
return lines:sub(start_position, current_position)
end
liluat.private.string_lines = string_lines
-- escape a string for use in lua patterns
-- (this simply prepends all non alphanumeric characters with '%'
local function escape_pattern(text)
return text:gsub("([^%w])", "%%%1" --[[function (match) return "%"..match end--]])
end
liluat.private.escape_pattern = escape_pattern
-- recursively copy a table
local function clone_table(table)
local clone = {}
for key, value in pairs(table) do
if type(value) == "table" then
clone[key] = clone_table(value)
else
clone[key] = value
end
end
return clone
end
liluat.private.clone_table = clone_table
-- recursively merge two tables, the second one has precedence
-- if 'shallow' is set, the second table isn't copied recursively,
-- its content is only referenced instead
local function merge_tables(a, b, shallow)
a = a or {}
b = b or {}
local merged = clone_table(a)
for key, value in pairs(b) do
if (type(value) == "table") and (not shallow) then
if a[key] then
merged[key] = merge_tables(a[key], value)
else
merged[key] = clone_table(value)
end
else
merged[key] = value
end
end
return merged
end
liluat.private.merge_tables = merge_tables
local default_options = {
start_tag = "{{",
end_tag = "}}",
trim_right = "code",
trim_left = "code"
}
-- initialise table of options (use the provided, default otherwise)
local function initialise_options(options)
return merge_tables(default_options, options)
end
-- creates an iterator that iterates over all chunks in the given template
-- a chunk is either a template delimited by start_tag and end_tag or a normal text
-- the iterator also returns the type of the chunk as second return value
local function all_chunks(template, options)
options = initialise_options(options)
-- pattern to match a template chunk
local template_pattern = escape_pattern(options.start_tag) .. "([+-]?)(.-)([+-]?)" .. escape_pattern(options.end_tag)
local include_pattern = "^"..escape_pattern(options.start_tag) .. "[+-]?include:(.-)[+-]?" .. escape_pattern(options.end_tag)
local expression_pattern = "^"..escape_pattern(options.start_tag) .. "[+-]?=(.-)[+-]?" .. escape_pattern(options.end_tag)
local position = 1
return function ()
if not position then
return nil
end
local template_start, template_end, trim_left, template_capture, trim_right = template:find(template_pattern, position)
local chunk = {}
if template_start == position then -- next chunk is a template chunk
if trim_left == "+" then
chunk.trim_left = false
elseif trim_left == "-" then
chunk.trim_left = true
end
if trim_right == "+" then
chunk.trim_right = false
elseif trim_right == "-" then
chunk.trim_right = true
end
local include_start, include_end, include_capture = template:find(include_pattern, position)
local expression_start, expression_end, expression_capture
if not include_start then
expression_start, expression_end, expression_capture = template:find(expression_pattern, position)
end
if include_start then
chunk.type = "include"
chunk.text = include_capture
elseif expression_start then
chunk.type = "expression"
chunk.text = expression_capture
else
chunk.type = "code"
chunk.text = template_capture
end
position = template_end + 1
return chunk
elseif template_start then -- next chunk is a text chunk
chunk.type = "text"
chunk.text = template:sub(position, template_start - 1)
position = template_start
return chunk
else -- no template chunk found --> either text chunk until end of file or no chunk at all
chunk.text = template:sub(position)
chunk.type = "text"
position = nil
return (#chunk.text > 0) and chunk or nil
end
end
end
liluat.private.all_chunks = all_chunks
local function read_entire_file(path)
assert(path)
local file = assert(io.open(path))
local file_content = file:read('*a')
file:close()
return file_content
end
liluat.private.read_entire_file = read_entire_file
-- a whitelist of allowed functions
local sandbox_whitelist = {
ipairs = ipairs,
next = next,
pairs = pairs,
rawequal = rawequal,
rawget = rawget,
rawset = rawset,
select = select,
tonumber = tonumber,
tostring = tostring,
type = type,
unpack = unpack,
string = string,
table = table,
math = math,
os = {
date = os.date,
difftime = os.difftime,
time = os.time,
},
coroutine = coroutine
}
-- puts line numbers in front of a string and optionally highlights a single line
local function prepend_line_numbers(lines, first, highlight)
first = (first and (first >= 1)) and first or 1
lines = lines:gsub("\n$", "") -- make sure the last line isn't empty
lines = lines:gsub("^\n", "") -- make sure the first line isn't empty
local current_line = first + 1
return string.format("%3d: ", first) .. lines:gsub('\n', function ()
local highlight_char = ' '
if current_line == tonumber(highlight) then
highlight_char = '> '
end
local replacement = string.format("\n%3d:%s", current_line, highlight_char)
current_line = current_line + 1
return replacement
end)
end
liluat.private.prepend_line_numbers = prepend_line_numbers
-- creates a function in a sandbox from a given code,
-- name of the execution context and an environment
-- that will be available inside the sandbox,
-- optionally overwrite the whitelist
local function sandbox(code, name, environment, whitelist, reference)
whitelist = whitelist or sandbox_whitelist
name = name or 'unknown'
-- prepare the environment
environment = merge_tables(whitelist, environment, reference)
local func
local error_message
if setfenv then --Lua 5.1 and compatible
if code:byte(1) == 27 then
error("Lua bytecode not permitted.", 2)
end
func, error_message = loadstring(code)
if func then
setfenv(func, environment)
end
else -- Lua 5.2 and later
func, error_message = load(code, name, 't', environment)
end
-- handle compile error and print pretty error message
if not func then
local line_number, message = error_message:match(":(%d+):(.*)")
-- lines before and after the error
local lines = string_lines(code, line_number - 3, line_number + 3)
error(
'Syntax error in sandboxed code "' .. name .. '" in line ' .. line_number .. ':\n'
.. message .. '\n\n'
.. prepend_line_numbers(lines, line_number - 3, line_number),
3
)
end
return func
end
liluat.private.sandbox = sandbox
local function parse_string_literal(string_literal)
return sandbox('return' .. string_literal, nil, nil, {})()
end
liluat.private.parse_string_literal = parse_string_literal
-- add an include to the include_list and throw an error if
-- an inclusion cycle is detected
local function add_include_and_detect_cycles(include_list, path)
local parent = include_list[0]
while parent do -- while the root hasn't been reached
if parent[path] then
error("Cyclic inclusion detected")
end
parent = parent[0]
end
include_list[path] = {
[0] = include_list
}
end
liluat.private.add_include_and_detect_cycles = add_include_and_detect_cycles
-- extract the name of a directory from a path
local function dirname(path)
return path:match("^(.*/).-$") or ""
end
liluat.private.dirname = dirname
-- splits a template into chunks
-- chunks are either a template delimited by start_tag and end_tag
-- or a text chunk (everything else)
-- @return table
local function parse(template, options, output, include_list, current_path)
options = initialise_options(options)
current_path = current_path or "." -- current include path
include_list = include_list or {} -- a list of files that were included
local output = output or {}
for chunk in all_chunks(template, options) do
-- handle includes
if chunk.type == "include" then -- include chunk
local include_path_literal = chunk.text
local path = parse_string_literal(include_path_literal)
-- build complete path
if path:find("^/") then
--absolute path, don't modify
elseif options.base_path then
path = options.base_path .. "/" .. path
else
path = dirname(current_path) .. path
end
add_include_and_detect_cycles(include_list, path)
local included_template = read_entire_file(path)
parse(included_template, options, output, include_list[path], path)
elseif (chunk.type == "text") and output[#output] and (output[#output].type == "text") then
-- ensure that no two text chunks follow each other
output[#output].text = output[#output].text .. chunk.text
else -- other chunk
table.insert(output, chunk)
end
end
return output
end
liluat.private.parse = parse
-- inline included template files
-- @return string
function liluat.inline(template, options, start_path)
options = initialise_options(options)
local output = {}
for _,chunk in ipairs(parse(template, options, nil, nil, start_path)) do
if chunk.type == "expression" then
table.insert(output, options.start_tag .. "=" .. chunk.text .. options.end_tag)
elseif chunk.type == "code" then
table.insert(output, options.start_tag .. chunk.text .. options.end_tag)
else
table.insert(output, chunk.text)
end
end
return table.concat(output)
end
-- @return { string }
function liluat.get_dependencies(template, options, start_path)
options = initialise_options(options)
local include_list = {}
parse(template, options, nil, include_list, start_path)
local dependencies = {}
local have_seen = {} -- list of includes that were already added
local function recursive_traversal(list)
for key, value in pairs(list) do
if (type(key) == "string") and (not have_seen[key]) then
have_seen[key] = true
table.insert(dependencies, key)
recursive_traversal(value)
end
end
end
recursive_traversal(include_list)
return dependencies
end
-- compile a template into lua code
-- @return { name = string, code = string / function}
function liluat.compile(template, options, template_name, start_path)
options = initialise_options(options)
template_name = template_name or 'liluat.compile'
local output_function = "__liluat_output_function"
-- split the template string into chunks
local lexed_template = parse(template, options, nil, nil, start_path)
-- table of code fragments the template is compiled into
local lua_code = {}
for i, chunk in ipairs(lexed_template) do
-- check if the chunk is a template (either code or expression)
if chunk.type == "expression" then
table.insert(lua_code, output_function..'('..chunk.text..')')
elseif chunk.type == "code" then
table.insert(lua_code, chunk.text)
else --text chunk
-- determine if this block needs to be trimmed right
-- (strip newline)
local trim_right = false
if lexed_template[i - 1] and (lexed_template[i - 1].trim_right == true) then
trim_right = true
elseif lexed_template[i - 1] and (lexed_template[i - 1].trim_right == false) then
trim_right = false
elseif options.trim_right == "all" then
trim_right = true
elseif options.trim_right == "code" then
trim_right = lexed_template[i - 1] and (lexed_template[i - 1].type == "code")
elseif options.trim_right == "expression" then
trim_right = lexed_template[i - 1] and (lexed_template[i - 1].type == "expression")
end
-- determine if this block needs to be trimmed left
-- (strip whitespaces in front)
local trim_left = false
if lexed_template[i + 1] and (lexed_template[i + 1].trim_left == true) then
trim_left = true
elseif lexed_template[i + 1] and (lexed_template[i + 1].trim_left == false) then
trim_left = false
elseif options.trim_left == "all" then
trim_left = true
elseif options.trim_left == "code" then
trim_left = lexed_template[i + 1] and (lexed_template[i + 1].type == "code")
elseif options.trim_left == "expression" then
trim_left = lexed_template[i + 1] and (lexed_template[i + 1].type == "expression")
end
if trim_right and trim_left then
-- both at once
if i == 1 then
if chunk.text:find("^.*\n") then
chunk.text = chunk.text:match("^(.*\n)%s-$")
elseif chunk.text:find("^%s-$") then
chunk.text = ""
end
elseif chunk.text:find("^\n") then --have to trim a newline
if chunk.text:find("^\n.*\n") then --at least two newlines
chunk.text = chunk.text:match("^\n(.*\n)%s-$") or chunk.text:match("^\n(.*)$")
elseif chunk.text:find("^\n%s-$") then
chunk.text = ""
else
chunk.text = chunk.text:gsub("^\n", "")
end
else
chunk.text = chunk.text:match("^(.*\n)%s-$") or chunk.text
end
elseif trim_left then
if i == 1 and chunk.text:find("^%s-$") then
chunk.text = ""
else
chunk.text = chunk.text:match("^(.*\n)%s-$") or chunk.text
end
elseif trim_right then
chunk.text = chunk.text:gsub("^\n", "")
end
if not (chunk.text == "") then
table.insert(lua_code, output_function..'('..string.format("%q", chunk.text)..')')
end
end
end
return {
name = template_name,
code = table.concat(lua_code, '\n')
}
end
-- compile a file
-- @return { name = string, code = string / function }
function liluat.compile_file(filename, options)
return liluat.compile(read_entire_file(filename), options, filename, filename)
end
-- @return a coroutine function
function liluat.render_coroutine(template, environment, options)
options = initialise_options(options)
environment = merge_tables({__liluat_output_function = coroutine.yield}, environment, options.reference)
return sandbox(template.code, template.name, environment, nil, options.reference)
end
-- @return string
function liluat.render(t, env, options)
options = initialise_options(options)
local result = {}
-- add closure that renders the text into the result table
env = merge_tables({
__liluat_output_function = function (text)
table.insert(result, text) end
},
env,
options.reference
)
-- compile and run the lua code
local render_function = sandbox(t.code, t.name, env, nil, options.reference)
local status, error_message = pcall(render_function)
if not status then
local line_number, message = error_message:match(":(%d+):(.*)")
-- lines before and after the error
local lines = string_lines(t.code, line_number - 3, line_number + 3)
error(
'Runtime error in sandboxed code "' .. t.name .. '" in line ' .. line_number .. ':\n'
.. message .. '\n\n'
.. prepend_line_numbers(lines, line_number - 3, line_number),
2
)
end
return table.concat(result)
end
return liluat

View file

@ -1,5 +0,0 @@
_: {
services.dunst = {
enable = true;
};
}

View file

@ -1,297 +0,0 @@
{
pkgs,
lib,
std,
config,
...
}: let
inherit (std) list;
inherit (lib.modules) mkMerge;
inherit (lib) mkDefault mapAttrs;
in {
home.packages = with pkgs; [
maim
pcmanfm
pavucontrol
xclip
];
services.i3gopher.enable = true;
xsession.windowManager.i3 = let
modifier = "Mod4";
other_modifier = "Mod1";
mod = modifier;
mod2 = other_modifier;
runCommand = "${config.programs.rofi.finalPackage}/bin/rofi -show combi -modes combi";
workspaceNames = {
"1" = " Term";
"2" = " GW2";
"3" = " GW1";
"4" = " Web";
"11" = " IM";
"12" = " Web";
"13" = " Media";
"14" = " Music";
};
workspaceNamer = num: let
numStr = builtins.toString num;
in
if workspaceNames ? ${numStr}
then "${numStr}:${workspaceNames.${numStr}}"
else "${numStr}:${numStr}";
lockCommand = "sh -c '${pkgs.i3lock-fancy-rapid}/bin/i3lock 5 3 & sleep 5 && xset dpms force off'";
actionMode = "(l) lock, (e) logout, (s) suspend, (h) hibernate, (r) reboot, (Shift+s) shutdown";
gapsMode = "Gaps: (o) outer, (i) inner";
gapsOuterMode = "Outer Gaps: +|-|0 (local), Shift + +|-|0 (global)";
gapsInnerMode = "Inner Gaps: +|-|0 (local), Shift + +|-|0 (global)";
in {
enable = true;
extraConfig = let
displayWorkspace = display: workspace: ''
workspace "${workspaceNamer (builtins.toString workspace)}" output ${display}
'';
displayBindings =
list.map (v: displayWorkspace "DP-2" v) (list.range 1 9)
++ [(displayWorkspace "DP-2" 10)]
++ list.map (v: displayWorkspace "HDMI-0" (11 + v)) (list.range 1 12);
displayBindingsStr = lib.concatLines displayBindings;
in ''
${displayBindingsStr}
for_window [class="^steam_app_default$"] floating enable, fullscreen disable, resize set width 3840 px height 2132 px, move position center, border pixel 1
'';
config = {
inherit modifier;
fonts = {
size = 10.0;
style = "Regular";
names = [
"Monaspace Krypton"
"FontAwesome 6"
];
};
startup = [
{
command = "~/.screenlayout/main.sh";
notification = false;
}
{
command = "blueman-applet";
notification = false;
}
];
keybindings = let
bindWorkspace = key: workspace: {
"${mod}+${key}" = "workspace number ${workspaceNamer workspace}";
"${mod}+shift+${key}" = "move container to workspace number ${workspaceNamer workspace}";
};
mapDefaultAttrs = e: mapAttrs (_: mkDefault) e;
workspaceBindings =
list.map (v: bindWorkspace v "${v}") (list.map builtins.toString (list.range 1 9))
++ [
(
bindWorkspace "0" "10"
)
]
++ list.imap (i: v: bindWorkspace v "${toString (11 + i)}") (list.map (n: "F${builtins.toString n}") (std.list.range 1 12));
normalBindings = {
"Print" = "exec --no-startup-id maim \"/home/$USER/Pictures/$(date).png\"";
"${mod2}+Print" = "exec --no-startup-id maim --window $(xdotool getactivewindow) \"/home/$USER/Pictures/Screenshots/$(date).png\"";
"Shift+Print" = "exec --no-startup-id maim --select \"/home/$USER/Pictures/Screenshots/$(date).png\"";
"Ctrl+Print" = "exec --no-startup-id maim | xclip -selection clipboard -t image/png";
"Ctrl+${mod2}+Print" = "exec --no-startup-id maim --window $(xdotool getactivewindow) | xclip -selection clipboard -t image/png";
"Ctrl+Shift+Print" = "exec --no-startup-id maim --select | xclip -selection clipboard -t image/png";
"${mod}+r" = "exec --no-startup-id ${runCommand}";
"${mod}+p" = "mode resize";
"${mod}+x" = "exec --no-startup-id sh -c '${pkgs.maim}/bin/maim -s | xclip -selection clipboard -t image/png'";
"${mod}+Shift+x" = "exec ${lockCommand}";
"${mod}+Return" = "exec --no-startup-id ${config.programs.wezterm.package}/bin/wezterm";
"${mod}+Tab" = "workspace back_and_forth";
"${mod}+Shift+Tab" = "exec --no-startup-id ${config.services.i3gopher.focus-last}";
"${mod}+Shift+g" = ''mode "${gapsMode}"'';
"${mod}+Delete" = ''mode "${actionMode}"'';
};
in
mkMerge (map mapDefaultAttrs ([normalBindings] ++ workspaceBindings));
assigns = {
${workspaceNamer 2} = [
{
class = "^steam_app_default$";
title = "^Guild Wars 2$";
}
];
${workspaceNamer 3} = [
{
class = "^steam_app_default$";
title = "^Guild Wars$";
}
];
${workspaceNamer 11} = [
{
class = "^Discord$";
}
];
${workspaceNamer 13} = [
{
class = "^mpv$";
}
];
${workspaceNamer 14} = [
{
class = "^Spotify$";
}
];
};
modes = let
defaultPath = {
"Return" = "mode default";
"Escape" = "mode default";
"${mod}+z" = "mode default";
};
in {
${gapsOuterMode} =
defaultPath
// {
"equal" = "gaps outer current plus 5";
"minus" = "gaps outer current minus 5";
"0" = "gaps outer current set 0";
"plus" = "gaps outer all plus 5";
"Shift+minus" = "gaps outer all minus 5";
"Shift+0" = "gaps outer all set 0";
};
${gapsInnerMode} =
defaultPath
// {
"equal" = "gaps inner current plus 5";
"minus" = "gaps inner current minus 5";
"0" = "gaps inner current set 0";
"plus" = "gaps inner all plus 5";
"Shift+minus" = "gaps inner all minus 5";
"Shift+0" = "gaps inner all set 0";
};
${gapsMode} =
defaultPath
// {
"o" = ''mode "${gapsOuterMode}"'';
"i" = ''mode "${gapsInnerMode}"'';
};
${actionMode} =
defaultPath
// {
"l" = "exec ${lockCommand}, mode default";
"e" = "exec swaymsg exit, mode default";
"s" = "exec systemctl suspend, mode default";
"h" = "exec systemctl hibernate, mode default";
"r" = "exec systemctl reboot, mode default";
"Shift+s" = "exec systemctl shutdown, mode default";
};
resize =
defaultPath
// {
"a" = "resize shrink width 4 px or 4 ppt";
"s" = "resize shrink height 4 px or 4 ppt";
"w" = "resize grow height 4 px or 4 ppt";
"d" = "resize grow width 4 px or 4 ppt";
"Left" = "resize shrink width 4 px or 4 ppt";
"Down" = "resize shrink height 4 px or 4 ppt";
"Up" = "resize grow height 4 px or 4 ppt";
"Right" = "resize grow width 4 px or 4 ppt";
};
};
workspaceAutoBackAndForth = true;
colors = {
focused = {
border = "$lavender";
background = "$base";
text = "$text";
indicator = "$rosewater";
childBorder = "$lavender";
};
focusedInactive = {
border = "$overlay0";
background = "$base";
text = "$text";
indicator = "$rosewater";
childBorder = "$overlay0";
};
unfocused = {
border = "$overlay0";
background = "$base";
text = "$text";
indicator = "$rosewater";
childBorder = "$overlay0";
};
urgent = {
border = "$peach";
background = "$base";
text = "$peach";
indicator = "$overlay0";
childBorder = "$peach";
};
placeholder = {
border = "$overlay0";
background = "$base";
text = "$text";
indicator = "$overlay0";
childBorder = "$overlay0";
};
background = "$base00";
};
bars = [
{
# as if anyone was questioning that,
position = "bottom";
fonts = {
names = [
"Monaspace Krypton"
"FontAwesome 6 Free"
"FontAwesome 6 Brands"
];
size = 10.0;
};
colors = {
background = "$base00";
statusline = "$text";
separator = "$text";
focusedBackground = "$base";
focusedStatusline = "$text";
focusedSeparator = "$base";
focusedWorkspace = {
border = "$base";
background = "$mauve";
text = "$crust";
};
activeWorkspace = {
border = "$base";
background = "$surface2";
text = "$text";
};
inactiveWorkspace = {
border = "$base";
background = "$base";
text = "$text";
};
urgentWorkspace = {
border = "$base";
background = "$red";
text = "$crust";
};
};
trayOutput = "primary";
extraConfig = ''
strip_workspace_numbers yes
'';
statusCommand = "${pkgs.i3status-rust}/bin/i3status-rs ${config.xdg.configHome}/i3status-rust/config-gaybar.toml";
}
];
};
};
}

View file

@ -1,73 +0,0 @@
{pkgs, ...}: {
programs.i3status-rust = {
enable = true;
bars = {
# YOU! I WANNA TAKE YOU TO A
gaybar = {
settings = {
icons = {
icons = "awesome6";
overrides = {
caffeine_on = "";
caffeine_off = "";
};
};
};
blocks = [
{
block = "cpu";
interval = 1;
}
{
block = "load";
interval = 1;
format = " $icon $1m ";
}
{
block = "memory";
format = " $icon $mem_used_percents.eng(w:2) $zram_comp_ratio ";
}
{
block = "memory";
format = " $icon_swap $swap_used_percents.eng(w:2) ";
}
{
block = "nvidia_gpu";
format = " $icon $utilization $memory $temperature ";
}
{
block = "hueshift";
}
{
block = "music";
format = " $icon {$combo.str(max_w:60) $play |}";
}
{
block = "sound";
format = " $icon {$volume.eng(w:2) |}";
}
{
block = "notify";
format = " $icon {($notification_count.eng(w:1)) |}";
}
{
block = "toggle";
command_on = "${pkgs.xorg.xset}/bin/xset -dpms";
command_off = "${pkgs.xorg.xset}/bin/xset +dpms";
format = " $icon DPMS ";
command_state = ''${pkgs.xorg.xset}/bin/xset q | ${pkgs.gnugrep}/bin/grep -F "DPMS is Disabled"'';
icon_on = "caffeine_on";
icon_off = "caffeine_off";
state_on = "info";
}
{
block = "time";
interval = 1;
format = " $icon $timestamp.datetime(f:'%F %T %Z') ";
}
];
theme = "ctp-latte";
};
};
};
}

View file

@ -1,8 +0,0 @@
_: {
services.picom = {
enable = false;
backend = "glx";
shadow = false;
vSync = false;
};
}

View file

@ -1,6 +0,0 @@
_: {
services.gammastep = {
enable = true;
provider = "geoclue2";
};
}

View file

@ -1,19 +0,0 @@
{
pkgs,
config,
...
}: {
home.packages = [
config.programs.rofi.finalPackage
];
programs.rofi = {
enable = true;
font = "Monaspace Krypton";
terminal = "wezterm";
plugins = with pkgs; [
rofi-games
rofimoji
rofi-rbw
];
};
}

View file

@ -1,2 +0,0 @@
_: {
}

View file

@ -1,68 +0,0 @@
{pkgs, ...}: {
home.sessionVariables = {
QT_QPA_PLATFORMTHEME = "qt5ct";
};
home.packages = with pkgs.kdePackages; [
kscreen
pkgs.xwayland
kscreen
libkscreen
kscreenlocker
kactivitymanagerd
kde-cli-tools
kglobalacceld # keyboard shortcut daemon
kwrited # wall message proxy, not to be confused with kwrite
baloo # system indexer
milou # search engine atop baloo
kdegraphics-thumbnailers # pdf etc thumbnailer
polkit-kde-agent-1 # polkit auth ui
plasma-desktop
plasma-workspace
drkonqi # crash handler
kde-inotify-survey # warns the user on low inotifywatch limits
# Application integration
libplasma # provides Kirigami platform theme
plasma-integration # provides Qt platform theme
kde-gtk-config # syncs KDE settings to GTK
# Artwork + themes
breeze
breeze-icons
breeze-gtk
ocean-sound-theme
plasma-workspace-wallpapers
pkgs.hicolor-icon-theme # fallback icons
qqc2-breeze-style
qqc2-desktop-style
# misc Plasma extras
kdeplasma-addons
pkgs.xdg-user-dirs # recommended upstream
# Plasma utilities
kmenuedit
kinfocenter
plasma-systemmonitor
ksystemstats
libksysguard
systemsettings
kcmutils
pkgs.plasma-applet-commandoutput
];
programs.plasma = {
configFile = {
"kded5rc"."PlasmaBrowserIntegration"."shownCount" = 1;
"kdeglobals"."WM"."activeBackground" = "231,232,235";
"kdeglobals"."WM"."activeBlend" = "231,232,235";
"kdeglobals"."WM"."activeForeground" = "92,97,108";
"kdeglobals"."WM"."inactiveBackground" = "231,232,235";
"kdeglobals"."WM"."inactiveBlend" = "231,232,235";
"kdeglobals"."WM"."inactiveForeground" = "163,165,172";
"kdeglobals"."General"."BrowserApplication" = "firefox.desktop";
"kdeglobals"."General"."TerminalService" = "org.wezfurlong.wezterm.desktop";
"kxkbrc"."Layout"."ResetOldOptions" = true;
"kxkbrc"."Layout"."Options" = "terminate:ctrl_alt_bksp,ctrl:hyper_capscontrol";
};
};
}

View file

@ -1,16 +0,0 @@
{pkgs, ...}: {
xdg.configFile."menus/applications.menu".source = "${pkgs.kdePackages.plasma-workspace}/etc/xdg/menus/plasma-applications.menu";
qt = {
enable = false;
platformTheme.package = with pkgs.kdePackages; [
plasma-integration
# I don't remember why I put this is here, maybe it fixes the theme of the system setttings
systemsettings
];
style = {
package = pkgs.kdePackages.breeze;
name = "Breeze";
};
};
systemd.user.sessionVariables = {QT_QPA_PLATFORMTHEME = "qt6ct";};
}

View file

@ -1,4 +1,9 @@
{pkgs, config, lib, ...}: let
{
pkgs,
config,
lib,
...
}: let
inherit (lib.meta) getExe getExe';
in {
programs.niri.settings.spawn-at-startup = let

View file

@ -183,7 +183,8 @@ in {
mediaBindingsAvizo = let
lightctl = getExe' config.services.avizo.package "lightctl";
volumectl = getExe' config.services.avizo.package "volumectl";
in mkIf config.services.avizo.enable {
in
mkIf config.services.avizo.enable {
"XF86MonBrightnessUp".action = sh ''${lightctl} up'';
"XF86MonBrightnessDown".action = sh ''${volumectl} down'';
"XF86AudioRaiseVolume" = {
@ -201,7 +202,8 @@ in {
};
mediaBindingsSwayOSD = let
swayosd-client = getExe' config.services.swayosd.package "swayosd-client";
in mkIf config.services.swayosd.enable {
in
mkIf config.services.swayosd.enable {
"XF86MonBrightnessUp".action = sh ''${swayosd-client} --brightness raise'';
"XF86MonBrightnessDown".action = sh ''${swayosd-client} --brightness lower'';
"XF86AudioRaiseVolume" = {
@ -225,7 +227,8 @@ in {
"XF86AudioMute".action = sh ''${parent.services.wireplumber.package}/bin/wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle'';
};
in
mkMerge (workspaceBindings ++ [
mkMerge (workspaceBindings
++ [
stockBindings
personalBindings
mediaBindingsCommon

View file

@ -1,7 +1,4 @@
{
config,
...
}: {
{config, ...}: {
sops.secrets.konawall-py-env = {
sopsFile = ./konawall.yaml;
};

View file

@ -3,11 +3,11 @@
enable = true;
timeouts = [
{
timeout = 180;
timeout = 600;
command = "${config.programs.swaylock.package}/bin/swaylock* -f";
}
{
timeout = 600;
timeout = 1200;
command = "${config.programs.niri.package}/bin/niri msg action power-off-monitors";
}
];

View file

@ -6,7 +6,7 @@
screenshots = true;
indicator = true;
clock = true;
grace = 2;
grace = 10;
fade-in = 2;
effect-blur = "7x5";
effect-vignette = "0.5:0.5";

View file

@ -1,9 +1,4 @@
{
lib,
config,
pkgs,
...
}:
_:
#let
# theme = with config.lib.stylix.colors.withHashtag; pkgs.writeTextFile {
# name = "swayosd-css";

View file

@ -1,8 +0,0 @@
_: {
services.barrier.client = {
enable = true;
enableCrypto = true;
enableDragDrop = true;
server = "10.1.1.153";
};
}

View file

@ -1,21 +0,0 @@
{pkgs, ...}: {
home.packages = with pkgs; [
adwaita-icon-theme
];
gtk = {
enable = true;
font = {
name = "Iosevka";
size = 9;
};
iconTheme = {
name = "Maia";
package = pkgs.maia-icon-theme;
};
theme = {
name = "Adapta";
package = pkgs.adapta-gtk-theme;
};
};
}

View file

@ -1,7 +0,0 @@
default partial alphanumeric_keys
xkb_symbols "basic" {
include "us(altgr-intl)"
name[Group1] = "English (US, international with pound sign)";
key <AD03> { [ e, E, EuroSign, cent ] };
key <AE03> { [ 3, numbersign, sterling] };
};

View file

@ -1,30 +0,0 @@
{
config,
pkgs,
...
}: let
inherit (config.base16) palette;
in {
systemd.user.services = {
mako = {
Unit = {
Description = "mako";
X-Restart-Triggers = [(toString config.xdg.configFile."mako/config".source)];
};
Service = {
ExecStart = "${pkgs.mako}/bin/mako";
Restart = "always";
};
Install = {WantedBy = ["graphical-session.target"];};
};
};
services.mako = {
enable = true;
font = "Iosevka 10";
defaultTimeout = 3000;
borderColor = palette.base08;
backgroundColor = "${palette.base00}BF";
textColor = palette.base05;
};
}

View file

@ -1,342 +0,0 @@
{
config,
pkgs,
lib,
std,
...
}: let
inherit (std) list;
inherit (lib.modules) mkMerge;
in {
programs.zsh.profileExtra = ''
# If running from tty1 start sway
if [ "$(tty)" = "/dev/tty1" ]; then
systemctl --user unset-environment \
SWAYSOCK \
I3SOCK \
WAYLAND_DISPLAY \
DISPLAY \
IN_NIX_SHELL \
__HM_SESS_VARS_SOURCED \
GPG_TTY \
NIX_PATH \
SHLVL
exec env --unset=SHLVL systemd-cat -t sway -- sway
fi
'';
home = {
sessionVariables = {
XDG_CURRENT_DESKTOP = "Unity";
XDG_SESSION_TYPE = "wayland";
WLR_DRM_DEVICES = "/dev/dri/card1";
};
packages = with pkgs; [
grim
slurp
swaylock-fancy
wl-clipboard
jq
quintom-cursor-theme
gsettings-desktop-schemas
glib
wofi
wmctrl
];
};
services = {
i3gopher.enable = true;
};
wayland.windowManager.sway = let
cfg = config.wayland.windowManager.sway.config;
in {
enable = true;
config = let
super = "Mod4";
alt = "Mod1";
actionMode = "(l) lock, (e) logout, (s) suspend, (h) hibernate, (r) reboot, (Shift+s) shutdown";
gapsMode = "Gaps: (o) outer, (i) inner";
gapsOuterMode = "Outer Gaps: +|-|0 (local), Shift + +|-|0 (global)";
gapsInnerMode = "Inner Gaps: +|-|0 (local), Shift + +|-|0 (global)";
lockCommand = "${pkgs.swaylock}/bin/swaylock";
in {
bars = [];
modes = let
defaultPath = {
"Return" = "mode default";
"Escape" = "mode default";
"${cfg.modifier}+z" = "mode default";
};
in {
${gapsOuterMode} =
defaultPath
// {
"equal" = "gaps outer current plus 5";
"minus" = "gaps outer current minus 5";
"0" = "gaps outer current set 0";
"plus" = "gaps outer all plus 5";
"Shift+minus" = "gaps outer all minus 5";
"Shift+0" = "gaps outer all set 0";
};
${gapsInnerMode} =
defaultPath
// {
"equal" = "gaps inner current plus 5";
"minus" = "gaps inner current minus 5";
"0" = "gaps inner current set 0";
"plus" = "gaps inner all plus 5";
"Shift+minus" = "gaps inner all minus 5";
"Shift+0" = "gaps inner all set 0";
};
${gapsMode} =
defaultPath
// {
"o" = "mode ${gapsOuterMode}";
"i" = "mode ${gapsInnerMode}";
};
${actionMode} =
defaultPath
// {
"l" = "exec ${lockCommand}, mode default";
"e" = "exec swaymsg exit, mode default";
"s" = "exec systemctl suspend, mode default";
"h" = "exec systemctl hibernate, mode default";
"r" = "exec systemctl reboot, mode default";
"Shift+s" = "exec systemctl shutdown, mode default";
};
resize =
defaultPath
// {
"a" = "resize shrink width 4 px or 4 ppt";
"s" = "resize shrink height 4 px or 4 ppt";
"w" = "resize grow height 4 px or 4 ppt";
"d" = "resize grow width 4 px or 4 ppt";
"Left" = "resize shrink width 4 px or 4 ppt";
"Down" = "resize shrink height 4 px or 4 ppt";
"Up" = "resize grow height 4 px or 4 ppt";
"Right" = "resize grow width 4 px or 4 ppt";
};
};
input = {
"*" = {
xkb_options = "compose:rctrl,ctrl:nocaps";
};
};
output = {
"*" = {
scale = "1.25";
};
};
gaps = {
smartBorders = "no_gaps";
};
fonts = {
names = ["Iosevka"];
style = "Regular";
size = 10.0;
};
terminal = "${pkgs.wezterm}/bin/wezterm";
modifier = super;
startup = [
];
window = {
border = 1;
titlebar = false;
hideEdgeBorders = "smart";
};
workspaceAutoBackAndForth = true;
floating = {
border = 1;
titlebar = false;
};
keybindings = let
pactl = "${config.home.nixosConfig.hardware.pulseaudio.package or pkgs.pulseaudio}/bin/pactl";
bindWorkspace = key: workspace: {
"${cfg.modifier}+${key}" = "workspace number ${workspace}";
"${cfg.modifier}+shift+${key}" = "move container to workspace number ${workspace}";
};
workspaceBindings =
list.map (v: bindWorkspace v "${v}") (list.map builtins.toString (list.range 1 9))
++ [
(
bindWorkspace "0" "10"
)
]
++ list.imap (i: v: bindWorkspace v "${toString (11 + i)}") (list.map (n: "F${builtins.toString n}") (std.list.range 1 12));
in
mkMerge ([
{
# modes
"${cfg.modifier}+Shift+g" = ''mode "${gapsMode}"'';
"${cfg.modifier}+Delete" = ''mode "${actionMode}"'';
# focus windows - ESDF
"${cfg.modifier}+s" = "focus left";
"${cfg.modifier}+d" = "focus down";
"${cfg.modifier}+e" = "focus up";
"${cfg.modifier}+f" = "focus right";
# focus windows - arrows
"${cfg.modifier}+Left" = "focus left";
"${cfg.modifier}+Down" = "focus down";
"${cfg.modifier}+Up" = "focus up";
"${cfg.modifier}+Right" = "focus right";
# move window / container - ESDF
"${cfg.modifier}+Shift+s" = "move left";
"${cfg.modifier}+Shift+d" = "move down";
"${cfg.modifier}+Shift+e" = "move up";
"${cfg.modifier}+Shift+f" = "move right";
# move window / container - arrows
"${cfg.modifier}+Shift+Left" = "move left";
"${cfg.modifier}+Shift+Down" = "move down";
"${cfg.modifier}+Shift+Up" = "move up";
"${cfg.modifier}+Shift+Right" = "move right";
# focus output - ESDF
"${cfg.modifier}+control+s" = "focus output left";
"${cfg.modifier}+control+d" = "focus output down";
"${cfg.modifier}+control+e" = "focus output up";
"${cfg.modifier}+control+f" = "focus output right";
# focus output - arrows
"${cfg.modifier}+control+Left" = "focus output left";
"${cfg.modifier}+control+Down" = "focus output down";
"${cfg.modifier}+control+Up" = "focus output up";
"${cfg.modifier}+control+Right" = "focus output right";
# move container to output - ESDF
"${cfg.modifier}+control+Shift+s" = "move container to output left";
"${cfg.modifier}+control+Shift+d" = "move container to output down";
"${cfg.modifier}+control+Shift+e" = "move container to output up";
"${cfg.modifier}+control+Shift+f" = "move container to output right";
# move container to output - arrows
"${cfg.modifier}+control+Shift+Left" = "move container to output left";
"${cfg.modifier}+control+Shift+Down" = "move container to output down";
"${cfg.modifier}+control+Shift+Up" = "move container to output up";
"${cfg.modifier}+control+Shift+Right" = "move container to output right";
# move workspace to output - ESDF
"${cfg.modifier}+control+Shift+Mod1+s" = "move workspace to output left";
"${cfg.modifier}+control+Shift+Mod1+d" = "move workspace to output down";
"${cfg.modifier}+control+Shift+Mod1+e" = "move workspace to output up";
"${cfg.modifier}+control+Shift+Mod1+f" = "move workspace to output right";
# move workspace to output - arrows
"${cfg.modifier}+control+Shift+Mod1+Left" = "move workspace to output left";
"${cfg.modifier}+control+Shift+Mod1+Down" = "move workspace to output down";
"${cfg.modifier}+control+Shift+Mod1+Up" = "move workspace to output up";
"${cfg.modifier}+control+Shift+Mod1+Right" = "move workspace to output right";
# process management - q
"${cfg.modifier}+q" = "exec ${cfg.menu}";
"${cfg.modifier}+Shift+q" = "kill";
"${cfg.modifier}+control+q" = "exec ${cfg.terminal}";
# focus parent/child - w
"${cfg.modifier}+w" = "focus parent";
"${cfg.modifier}+Shift+w" = "focus child";
# unused control
# split management - a
"${cfg.modifier}+a" = "splith";
"${cfg.modifier}+Shift+a" = "splitv";
"${cfg.modifier}+control+A" = "layout toggle split";
# resizing, reloading - r
# unused base
"${cfg.modifier}+Shift+r" = "mode resize";
"${cfg.modifier}+control+r" = "reload";
# layout handling - t
"${cfg.modifier}+t" = "layout tabbed";
"${cfg.modifier}+Shift+t" = "layout stacking";
"${cfg.modifier}+control+t" = "fullscreen toggle";
# locking - l
"${cfg.modifier}+l" = "exec ${lockCommand}";
# unused shift
# unused control
"control+${alt}+Delete" = "exec ${lockCommand}";
# floating - p
"${cfg.modifier}+p" = "focus mode_toggle";
"${cfg.modifier}+Shift+p" = "floating toggle";
# unused control
# workspace history switching - tab
"${cfg.modifier}+Tab" = "workspace back_and_forth";
"${cfg.modifier}+Shift+Tab" = "exec ${config.services.i3gopher.focus-last}";
# unused control
# multimedia / laptop
"XF86AudioPlay" = "exec --no-startup-id ${pkgs.playerctl}/bin/playerctl play-pause";
"XF86AudioLowerVolume" = "exec --no-startup-id ${pactl} set-sink-volume @DEFAULT_SINK@ -5%";
"XF86AudioRaiseVolume" = "exec --no-startup-id ${pactl} set-sink-volume @DEFAULT_SINK@ +5%";
"XF86AudioMute" = "exec --no-startup-id ${pactl} set-sink-mute @DEFAULT_SINK@ toggle";
"XF86AudioMute+Shift" = "exec --no-startup-id ${pactl} set-source-mute @DEFAULT_SOURCE@ toggle";
"XF86AudioMicMute" = "exec --no-startup-id ${pactl} set-source-mute @DEFAULT_SOURCE@ toggle";
"XF86MonBrightnessDown" = "exec ${pkgs.light}/bin/light -U 5";
"XF86MonBrightnessUp" = "exec ${pkgs.light}/bin/light -A 5";
}
]
++ workspaceBindings);
colors = let
inherit (config.base16) palette;
in {
focused = {
border = palette.base01;
background = palette.base0D;
text = palette.base07;
indicator = palette.base0D;
childBorder = palette.base0D;
};
focusedInactive = {
border = palette.base02;
background = palette.base04;
text = palette.base00;
indicator = palette.base04;
childBorder = palette.base04;
};
unfocused = {
border = palette.base01;
background = palette.base02;
text = palette.base06;
indicator = palette.base02;
childBorder = palette.base02;
};
urgent = {
border = palette.base03;
background = palette.base08;
text = palette.base00;
indicator = palette.base08;
childBorder = palette.base08;
};
};
seat.seat0.xcursor_theme = ''"Quintom Snow" 20'';
};
wrapperFeatures.gtk = true;
extraConfig = ''
title_align center
'';
};
}

View file

@ -1,97 +0,0 @@
{
kittywitch,
pkgs,
...
}: {
programs.waybar = {
enable = true;
style = let
template = kittywitch.sassTemplate {
name = "waybar-style";
src = ./waybar.sass;
};
in
template.source;
systemd.enable = true;
settings.main = {
layer = "top";
position = "top";
height = 18;
# Modules Placement
modules-left = [
"sway/workspaces"
"sway/mode"
"sway/window"
];
modules-center = [
"custom/clock"
"mpris"
];
modules-right = [
"network"
"temperature"
"idle_inhibitor"
"battery"
"tray"
];
# Modules Definition
"sway/workspaces" = {
format = "{icon}";
format-icons = {
# https://fontawesome.com/v5/cheatsheet
"1" = ""; # chats
"2" = ""; # cloud (browser)
"3" = ""; # music
"4" = ""; # brain
"5" = ""; # terminal >_
};
};
"sway/window" = {
format = "{}";
};
battery = {};
tray = {
show-passive-items = true;
icon-size = 12;
spacing = 2;
};
mpris = {
format = "{player_icon} {dynamic}";
format-paused = "{status_icon} {dynamic}";
player-icons = {
default = "";
brave = "";
mpv = "";
spotify = "";
};
status-icons = {
paused = "";
};
};
temperature = {
format = " {temperatureC}°C";
critical-threshold = 80;
};
idle_inhibitor = {
format = "{icon}";
format-icons = {
activated = "";
deactivated = "";
};
};
network = {
format-wifi = " {essid} ({signalStrength}%)";
format-ethernet = " {ipaddr}/{cidr}";
format-linked = " No IP";
format-disconnected = " Disconnected";
format-alt = "{ifname}: {ipaddr}/{cidr}";
};
"custom/clock" = {
exec = ''${pkgs.coreutils}/bin/date +"%a, %F %T %Z"'';
interval = 1;
};
};
};
}

View file

@ -1,84 +0,0 @@
*
padding: 0
margin: 0
border: none
border-radius: 0
background: none
font-family: "Iosevka", "Font Awesome 6 Free", "Font Awesome 6 Brands"
font-size: $font_size
text-shadow: none
box-shadow: none
%widget_unpadded
transition: none
background: $base01
color: $base07
margin: 0 4px
%widget
@extend %widget_unpadded
padding: 0 4px
window#waybar
background: rgba($base00, 0.9)
border-bottom: 2px solid transparent
// sway/workspaces
#workspaces
@extend %widget_unpadded
button
color: $base06
&.focused
color: $base07
background: $base0D
&:hover
transition: none
box-shadow: inherit
text-shadow: inherit
background: $base06
color: $base0C
// widgets
#mode, window#waybar #window,
#custom-clock, #mpris,
#pulseaudio, #backlight, #network, #temperature, #battery, #idle_inhibitor, #tray, #tray menu
@extend %widget
// hide when empty
window#waybar.empty #window
opacity: 0
// tooltips
tooltip
background: rgba($base00, 0.9)
label
color: $base07
// mpris player and state
#mpris
&.spotify
background: #191414
color: #1DB954
&.paused
background: $base01
color: $base03
/*.modules-left
#window
widget
label
margin: 0
&:first-child
margin-left: 0
&:last-child
margin-right: 0*/
.modules-center
.modules-right

View file

@ -1,20 +0,0 @@
{kittywitch, ...}: {
programs.wofi = {
enable = true;
settings = {
style = let
template = kittywitch.sassTemplate {
name = "wofi-style";
src = ./wofi.sass;
};
in
template.source;
insensitive = true;
allow_images = true;
hide_scroll = true;
width = "25%";
mode = "dmenu";
prompt = "";
};
};
}

View file

@ -1,26 +0,0 @@
#scroll
background: $base01
border: 1px solid $base03
#input
background: $base01
border: 1px solid $base0C
margin: 1em
background: $base02
color: $base04
window
font-family: $font
background: rgba($base00, .9)
border-radius: 1em
font-size: $font_size
color: $base07
#outer-box
margin: 1em
#entry
border-bottom: 1px dashed $base04
padding: .75em
&:selected
background-color: $base0D

View file

@ -1,16 +0,0 @@
_: {
xdg = {
enable = true;
userDirs = {
enable = true;
pictures = "$HOME/pictures";
videos = "$HOME/videos";
documents = "$HOME/docs";
download = "$HOME/downloads";
desktop = "$HOME/desktop";
templates = "$HOME/templates";
publicShare = "$HOME/shared";
music = "$HOME/music";
};
};
}

View file

@ -1,7 +0,0 @@
_: {
home.file = {
".xkb/symbols/us_gbp_map".source = ./layout.xkb;
};
home.keyboard = null;
}

View file

@ -1,32 +0,0 @@
{pkgs, ...}: {
home.pointerCursor = {
gtk.enable = true;
# x11.enable = true;
package = pkgs.chicago95;
name = "Chicago95";
size = 16;
};
gtk = {
enable = true;
iconTheme = {
name = "Chicago95-tux";
package = pkgs.chicago95;
};
theme = {
name = "Chicago95";
package = pkgs.chicago95;
};
cursorTheme = {
name = "Chicago95";
package = pkgs.chicago95;
};
font = {
name = "Monaspace Krypton";
size = 11;
};
};
}

View file

@ -1,42 +0,0 @@
{
inputs,
pkgs,
config,
...
}: let
konawallConfig = {
interval = 60 * 5;
rotate = true;
source = "konachan";
tags = [
"rating:s"
"touhou"
"score:>=50"
"width:>=1500"
];
logging = {
file = "INFO";
console = "DEBUG";
};
};
in {
systemd.user.services.konawall-py = {
Unit = {
Description = "konawall-py";
X-Restart-Triggers = [(toString config.xdg.configFile."konawall/config.toml".source)];
After = ["gnome-session.target" "network-online.target"];
Environment = [
"PYSTRAY_BACKEND=gtk"
];
};
Service = {
ExecStart = "${inputs.konawall-py.packages.${pkgs.system}.konawall-py}/bin/konawall";
Restart = "on-failure";
RestartSec = "1s";
};
Install = {WantedBy = ["graphical-session.target"];};
};
xdg.configFile = {
"konawall/config.toml".source = (pkgs.formats.toml {}).generate "konawall-config" konawallConfig;
};
}

View file

@ -1,15 +0,0 @@
{
lib,
pkgs,
...
}: let
inherit (lib.strings) fileContents;
in {
home.sessionVariables.GSM_SKIP_SSH_AGENT_WORKAROUND = "1";
# Disable gnome-keyring ssh-agent
xdg.configFile."autostart/gnome-keyring-ssh.desktop".text = ''
${fileContents "${pkgs.gnome-keyring}/etc/xdg/autostart/gnome-keyring-ssh.desktop"}
Hidden=true
'';
}

View file

@ -1,31 +0,0 @@
_: {
xfconf = {
settings = {
xsettings = {
"Xfce4/SyncThemes" = true;
"Net/IconThemeName" = "Chicago95-tux";
"Net/ThemeName" = "Chicago95";
};
xfce4-keyboard-shortcuts = {
"commands/custom/Super_L" = "xfce4-popup-whiskermenu";
};
xfce4-session = {
"startup/ssh-agent/enabled" = false;
};
xfce4-power-manager = {
"xfce4-power-manager/show-tray-icon" = false;
"xfce4-power-manager/general-notification" = true;
};
xfwm4 = {
"general/theme" = "Chicago95";
"general/title_font" = "Sans Bold 8";
"general/show_dock_shadow" = false;
};
xfce4-notifyd = {
"theme" = "Chicago95";
"notify-location" = "bottom-right";
};
};
enable = true;
};
}

View file

@ -19,7 +19,7 @@
opacity = {
desktop = 1.0;
applications = 1.0;
terminal = 0.8;
terminal = 0.9;
popups = 0.8;
};
fonts = {

View file

@ -4,7 +4,6 @@
enable = true;
package = pkgs.alacritty-graphics;
settings = {
};
};
}

View file

@ -1,4 +1,4 @@
{pkgs, ...}: {
_: {
stylix.targets.vesktop.enable = false;
programs.vesktop = {
enable = true;

View file

@ -2,9 +2,7 @@
pkgs,
nur,
...
}: let
defaultFont = "Monaspace Krypton";
in {
}: {
home.sessionVariables = {
BROWSER = "zen";
};
@ -49,6 +47,7 @@ in {
return-youtube-dislikes
ff2mpv
terms-of-service-didnt-read
web-clipper-obsidian
];
force = true;
};

View file

@ -1,5 +1,6 @@
{pkgs, ...}: {
home.packages = with pkgs; [
pavucontrol
tiled
aseprite
];
}

View file

@ -17,20 +17,30 @@ _: {
enable = true;
profiles = ["main"];
};
gmailAccount = mainEnable // {
gmailAccount =
mainEnable
// {
flavor = "gmail.com";
};
in {
primary = gmailAccount // katIdentity // {
primary =
gmailAccount
// katIdentity
// {
primary = true;
address = "kat@inskip.me";
};
home = gmailAccount // katIdentity // {
home =
gmailAccount
// katIdentity
// {
address = "kat.inskip@gmail.com";
};
dork = gmailAccount // dorkIdentity // {
dork =
gmailAccount
// dorkIdentity
// {
address = "dorkdev99@gmail.com";
};
};
}

View file

@ -1,15 +1,13 @@
{
config,
lib,
std,
pkgs,
...
}: let
inherit (lib.modules) mkIf;
inherit (std) string set;
initLua = pkgs.replaceVars ./init.lua ({
initLua = pkgs.replaceVars ./init.lua {
inity = config.programs.neovim.generatedConfigs.lua;
});
};
in {
stylix.targets.neovim = {
enable = true;

View file

@ -8,7 +8,7 @@
}: let
inherit (lib.attrsets) nameValuePair listToAttrs;
inherit (lib.modules) mkMerge mkIf;
inherit (std) string list serde;
inherit (std) string list;
in {
home.packages = with pkgs; [
# programs.zsh.enableAutosuggestions only includes nix-zsh-autocompletions

18
microvms/syncthing.nix Normal file
View file

@ -0,0 +1,18 @@
{
tree,
config,
...
}: {
imports = with tree.nixos; [
microvm.default
servers.syncthing
];
sops.secrets."${config.networking.hostName}-sops-age-key" = {
sopsFile = ./. + "${config.networking.hostName}.yaml";
};
microvm.credentialFiles = {
SOPS_AGE_KEY = sops.secrets."${config.networking.hostName}-sops-age-key".path;
};
networking.hostName = "syncthing";
services.syncthing.device_name = "daiyousei-syncthing";
}

View file

@ -15,7 +15,6 @@
}
));
};
in {
options = {
home = {

View file

@ -1,4 +1,10 @@
{ inputs, lib, pkgs, config, ... }: let
{
inputs,
lib,
pkgs,
config,
...
}: let
inherit (lib.options) mkOption mkEnableOption mkPackageOption;
inherit (lib.types) submodule path nullOr;
inherit (lib.modules) mkIf;

View file

@ -13,7 +13,7 @@
inherit (std) string set;
in {
options = let
inherit (lib.types) str listOf attrs unspecified enum;
inherit (lib.types) str listOf attrs nullOr unspecified enum bool;
inherit (lib.options) mkOption;
in {
name = mkOption {
@ -55,6 +55,18 @@ in {
type = unspecified;
internal = true;
};
microVM = {
state = mkOption {
description = "Does this system exist as a guest MicroVM?";
type = bool;
default = false;
};
host = mkOption {
description = "The hostname that is the host of this guest MicroVM";
type = nullOr str;
default = null;
};
};
};
config = {
system = let

3
nixos/common/tz.nix Normal file
View file

@ -0,0 +1,3 @@
_: {
time.timeZone = "America/Vancouver";
}

View file

@ -1,12 +0,0 @@
_: {
services.tzupdate.enable = true;
systemd.timers."tzupdate" = {
wantedBy = ["timers.target"];
timerConfig = {
OnBootSec = "5m";
OnUnitActiveSec = "5m";
Unit = "tzupdate.service";
};
};
}

58
nixos/container-host.nix Normal file
View file

@ -0,0 +1,58 @@
_: {
networking.useNetworkd = true;
systemd.network.netdevs."20-container".netdevConfig = {
Kind = "bridge";
Name = "container";
};
# Internet for containers!
networking.nat = {
enable = true;
# NAT66 exists and works. But if you have a proper subnet in
# 2000::/3 you should route that and remove this setting:
enableIPv6 = true;
# Change this to the interface with upstream Internet access
externalInterface = "enp0s6";
# The bridge where you want to provide Internet access
internalInterfaces = ["container"];
};
# container
systemd.network.networks."20-container" = {
matchConfig.Name = "container";
networkConfig = {
DHCPServer = true;
IPv6SendRA = true;
};
addresses = [
{
addressConfig.Address = "10.0.1.1/24";
}
{
addressConfig.Address = "fd12:3456:789b::1/64";
}
];
ipv6Prefixes = [
{
ipv6PrefixConfig.Prefix = "fd12:3456:789b::/64";
}
];
};
# Attach to containers
systemd.network.networks."21-container" = {
matchConfig.Name = "ve-*";
# Attach to the bridge that was configured above
networkConfig.Bridge = "container";
};
# Allow inbound traffic for the DHCP server
networking.firewall.allowedUDPPorts = [67];
users.users = {
# allow container access to zvol
container.extraGroups = ["disk"];
};
}

View file

@ -0,0 +1,3 @@
_: {
# TODO: more
}

View file

@ -1,4 +1,8 @@
{pkgs, config, lib, ...}: let
{
config,
lib,
...
}: let
inherit (lib.modules) mkForce;
in {
programs.regreet = {

62
nixos/microvm-host.nix Normal file
View file

@ -0,0 +1,62 @@
_: {
microvm = {
host.enable = true;
};
networking.useNetworkd = true;
systemd.network.netdevs."10-microvm".netdevConfig = {
Kind = "bridge";
Name = "microvm";
};
# Internet for microVMs!
networking.nat = {
enable = true;
# NAT66 exists and works. But if you have a proper subnet in
# 2000::/3 you should route that and remove this setting:
enableIPv6 = true;
# Change this to the interface with upstream Internet access
externalInterface = "enp0s6";
# The bridge where you want to provide Internet access
internalInterfaces = ["microvm"];
};
# MicroVM
systemd.network.networks."10-microvm" = {
matchConfig.Name = "microvm";
networkConfig = {
DHCPServer = true;
IPv6SendRA = true;
};
addresses = [
{
addressConfig.Address = "10.0.0.1/24";
}
{
addressConfig.Address = "fd12:3456:789a::1/64";
}
];
ipv6Prefixes = [
{
ipv6PrefixConfig.Prefix = "fd12:3456:789a::/64";
}
];
};
# Attach to microVMs
systemd.network.networks."11-microvm" = {
matchConfig.Name = "vm-*";
# Attach to the bridge that was configured above
networkConfig.Bridge = "microvm";
};
# Allow inbound traffic for the DHCP server
networking.firewall.allowedUDPPorts = [67];
users.users = {
# allow microvm access to zvol
microvm.extraGroups = ["disk"];
};
}

88
nixos/microvm/default.nix Normal file
View file

@ -0,0 +1,88 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkDefault;
inherit (lib.meta) getExe';
in {
# TODO: more
microvm = {
guest.enable = true;
optimize.enable = true;
vcpu = 2;
mem = 2048;
initialBalloonMem = 256;
balloon = true;
volumes = [
{
autoCreate = true;
mountPoint = "/var";
image = "var.img";
size = 256;
}
];
shares = [
{
tag = "ro-store";
source = "/nix/store";
mountPoint = "/nix/.ro-store";
}
];
};
boot = {
loader.grub.enable = false;
loader.systemd-boot.enable = false;
};
fileSystems = {
"/" = mkDefault {
fsType = "tmpfs";
};
};
services.fstrim.enable = false;
nix = {
gc.automatic = false;
};
hardware.enableRedistributableFirmware = false;
initrd.kernelModules = [
# required for net.netfilter.nf_conntrack_max appearing in sysfs early at boot
"nf_conntrack"
];
kernel.sysctl = let
limit = 2 * 1024;
mem =
if (config?microvm)
then config.microvm.mem
else limit;
in
lib.optionalAttrs (mem <= limit) {
# table overflow causing packets from nginx to the service to drop
# nf_conntrack: nf_conntrack: table full, dropping packet
"net.netfilter.nf_conntrack_max" = lib.mkDefault "65536";
};
kernelParams = [
# mitigations which cost the most performance and are the least real world relevant
# NOTE: keep in sync with baremetal.nix
"retbleed=off"
"gather_data_sampling=off" # Downfall
];
system.build.installBootLoader = getExe' pkgs.coreutils "true";
systemd.tmpfiles.rules = [
"d /home/root 0700 root root -" # createHome does not create it
];
users = {
mutableUsers = false;
# store root users files persistent, especially .bash_history
users."root" = {
createHome = true;
home = lib.mkForce "/home/root";
};
};
}

View file

@ -13,7 +13,7 @@
protonplus
gamescope-wsi
(lutris.override {
extraPkgs = pkgs: [
extraPkgs = _pkgs: [
#pkgs.gamescope
#pkgs.libnghttp2
#pkgs.winetricks
@ -25,7 +25,7 @@
#pkgs.umu-launcher
#pkgs.xdg-desktop-portal
];
extraLibraries = pkgs: [
extraLibraries = _pkgs: [
#pkgs.libunwind
#pkgs.xdg-desktop-portal
#pkgs.gvfs

View file

@ -1,8 +1,8 @@
{pkgs, ...}: {
programs.java = {
enable = false;
enable = true;
};
environment.systemPackages = with pkgs; [
#prismlauncher
prismlauncher
];
}

View file

@ -14,7 +14,10 @@ _: {
onCalendar = "weekly";
};
remotes = [
{ name = "flathub"; location = "https://dl.flathub.org/repo/flathub.flatpakrepo"; }
{
name = "flathub";
location = "https://dl.flathub.org/repo/flathub.flatpakrepo";
}
];
};
}

View file

@ -1,3 +0,0 @@
_: {
services.mullvad-vpn.enable = true;
}

View file

@ -0,0 +1,27 @@
{lib, ...}: let
inherit (lib.generators) toJSON;
mullvadSettings = builtins.toJSON {
allow_lan = true;
auto_connect = true;
block_when_disconnected = true;
};
in {
services.mullvad-vpn.enable = true;
#sops.secrets.mullvad-vpn-account-number = {
#sopsFile = ./secrets.yaml;
#};
systemd = {
services."mullvad-daemon".environment.MULLVAD_SETTINGS_DIR = "/var/lib/mullvad-vpn";
tmpfiles.settings."10-mullvad-settings" = {
"/var/lib/mullvad-vpn/settings.json"."C+" = {
group = "root";
mode = "0700";
user = "root";
argument = "${mullvadSettings}";
};
};
};
}

View file

@ -0,0 +1,111 @@
syncthing-key: ENC[AES256_GCM,data:+7LMqt1XAL0MKN34dTqk0A2WKgBRv5wPoQQtsPXJ4i89gzLt1GQADA5bTtIoplbc+Mfp+lk4pYwfxuViidZrqTZo2GfzYci3kmIBkOg3e+kntNtYBUx5oGfd2ksHKbkaO4+kJSmlgf52hAx/a0IejKk52If/MUofAQP8xNrxOt1PYnd3nVvojcDpnhUTFzZWuSMWUuuOrhzgu/HmjBZIThx13Wd1Iewfy/T24SdaRnrf2KnizMt4tKGsOYp5ApalHuknev6B/4uf77PU9GWRBOj8UAMNTz/J8haSHXOfXY57WZw9gRiLmwR5JF2UVF3ZjSUwMdQwC0HP1NbeOv3uFSQNh7goOUY/0NKt3GwCT73HNzCl/8piy9PmU9cfK4Ri,iv:aT4mPmxTFHphDeWVzIfr9vdfrSubTnMrc7tsZ+XIHLE=,tag:OeTD9w+y0ViJHQlqOKUpFg==,type:str]
syncthing-cert: ENC[AES256_GCM,data:k8E8aoFV486W4ZlxF6zzBteYmKYuaFnEip1RseA8RW6ahX3TUmF0FtnA6qrHYtgjzzSd/B3TQ1Ss3GOQBqYmcUIaI/4y12jlCF01DHoDvgWp8cNwO8WAOEY18Sb1g/ysY8bd+ms7bR3dyOG2UQ6ThRruWDMma7CalGl/uS2LupPJ4JcutiPXk2brPgPttU3BaeBO1Xrn+nFaE0oUnMQAVv10Iw8LuJE5uQ+ylF0/CNU+VFfSK1yMEYxNT4i9Y3nB8n9z3Ca/6R4sUbuGdVRYLzzbYkCSRgTbw6RsNuj2RvC8oLPBmnTXx42R7bFoirpOSHkMICI4qMrZTiF9+vxMdrTVlZvihiuDJndKgfxBv+1JTVlgTbdjMZYcHaJfy86BT9Q+4ydBbgGytVZoW+aDQwvM7W47JZZPl7edOKHTuJ0QiLyFIqnIvkP1WGSKIvNVxLLbl7Oy1QRCnDw1cJOIdcLOamJqDP928tPWbszJEN8duQ2tm37Ux1P74PfeDCUjP3jILQ+0rP7dY5BdGs3OB8yiMJ720lF0zrYFOfr5KtWguURR66Ac9blwtK3aP6XDfI/jwDgqD38eXIffMdX2Jkp9v8oxl7VNrQ29z88X4ofuKMjgvE5CHva0ZsLsDpp4n2DRLtRjxB9uEdu0nke17r6Jpe1W5nPjxbpSTniB8kxKVYVTuYi3D73vh84tBmxQAWfLkfjbccl0rQXnfBgtIHLzoF6eti/DVU5BbpMyMU+8YJq8iX8VlfqxXuetThFdhJ/kEc1LYIMOOAbraRkghi3um/hutMaoMD57arsW4NXvYJZBuEmdHXeKyoCUUzLx0Iu2tjJjis34RsKABfTw0qTku1AuOs97X7DbXUV8LX5oyzYMmE8lSSbslXQisff1oUby1W+YNqQPApBTAIolf2b4bE+UFrFmjTJHo+zhPYKb4Jqn6el896Fji0o+W3XJpakJ5Dd5R8cmUPxGxbfFQOPpndbTWcHgwc4I18YIC1QViEx20eDRZ+d/3/rBwWg9pkF8g7nbnBhPO6DOe/k1iG62X+QEmYIG9ys=,iv:r1HzTB/OHSbD/Ubgx9xmcAW2PUBpvjDPLo/Cfdwbqpc=,tag:CpcYJ9HwLuLmgNdlcnCl3A==,type:str]
sops:
shamir_threshold: 1
age:
- recipient: age1n4kdchmkk3rfkaknxhveqr2ftprdpgwckutt23y6u8639lazzuks77tgav
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArU2l6dkNDazRORSt0S24x
YnVsaWExTDZPNDlqeHBEWElzczlNakhIWWtvCmVpZ1VDK2tXbTFSdCs1V1FSU25C
eU5SN3lNdUFmbXdBTFBleU1abVo3WGMKLS0tIFJ3cTJEYnk5V3pzeUFXZkJZa1dt
ZmRlOW5aTHdydkxOOHJid042ZS8zTzgKoEo/dF29QJFxmri3NLPD8PHBzORgeF4W
Vqp/N6xg1ah2ot5fIalJdSeDmPV0T3O0mOfpDrrqSprQypHfwuXAbQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1cnu37d5fqyahh9vvc4hj6z6k8ur9ksuefln7sr6g3emmn927eutqxdawuh
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJbUZTb2RtYzFRai8ydWUx
cDEyK1Z4QWgzUmR4YlpVcGhidFV6YzVaN2hFCnRRaDRRYytMOVdacjVBTUx2d3J2
aHI3V2dNT0tldXB4RnFMOGRuRDl2RFUKLS0tIHljQ1ZuZGNvc1NrYThhM2VybVJa
NWJ2WlFTWGtyNDM4aVRvcVRoS3I4cmsK8LMWxGndQpu+7CLx0zDLYecqXOVqTgQk
iJ8/7LVOF/aoZDj6JNZ95sxlpqbN4vnEhgPMEByZJsmsAMpCHysd9w==
-----END AGE ENCRYPTED FILE-----
- recipient: age1a0m73qr8hhuz8xemv4vymf4wmpghm2hst8wgrn3pn65ext5mf4ksk0vsdm
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBlVW5xTElQeDFVWWJWTGln
Ung5b1pvajgzUEx3dDNVUnBrVGZjbndoWkVRCjcrOEowRm52Tmc1WjcxZlcwd0Zr
TVBQdzIxNTNBWVVVYVRhZ09Penh4ZXMKLS0tIHdKM0FXVGxsbWF4V1dQNGZXanFK
YWYrOUpiL1FnSFFFYTc3a0ppcDZTanMK29i69wWkJavEbDOfCIYQ09+LPjnemzbl
fGfJX4MIWWfN3gDv0PZHDxJ5i96IxkBxD1KKAcdBDJuakqo2Bp8bIA==
-----END AGE ENCRYPTED FILE-----
- recipient: age18hpxz0ghvswv9k30cle73prvnzrsuczqh87jjdk9fl50j3ddndmq9xae0n
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArbytGR0NPTTZLOW04YjF4
T3YxUkpYVXJlRDBFWE1IOGVzd0w0QytZYUVnCm5nVzZSN3V2aFE3MTRxeE5lWWxH
QUg2emtTMkRtV0xFeTd4OFVKY254WkkKLS0tIFBId2NrYi8wNWJrVEY0K25Sa2kv
WUFvaVA0aGVsTVJQTSttbHZtY2o2TlUK38aZgSUGSjY+9z5IYkvpB76MKePekElf
+7EVpmAnMQdtWOjRFgFuE4olT0kZ1ktClyDGPgZycY9POcKNuFLqWA==
-----END AGE ENCRYPTED FILE-----
- recipient: age1xgy03g3vjydsxcl0qpdgm8rahjcjq95ucxfwlgr22zwjx3p7jf2s9jk6u5
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJd29BUkMvd3lJbEp1eUhL
djB5T2oxNHlab0o2NXZVK3VjVnJ2KzFNbkJBCkFuUGhDeTcyWThwOERVb09ReWZT
ZVFEZzZXbDduRkprdXU1MW16RXg5RDAKLS0tIHVocUMwSnp3cVkrRU4zaU1nNmd4
Y3d3Y2xKaFQ1aEoxcFdPKzlhem1XcFEKwfBddjkvC+MOnJ2VtrrTaIc9q34xSAwN
hRm2rcM0ddRMPpt8urx0//22Xx8nChU/4UCIrUI/FBuQpXsjRHqLVg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1fv5dafs4n3r5n83qm2hfz7xmnflsz0xf9r3saralrptpgf8mvuxq4t8k3u
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTek9VVXdKYmR3bXp3NmZX
QzduT3NCRHhnWHlsYXkrYVg1U2VsdVFDMzA4CmthN2ltWXA1b3V4bWxmQjkrejlE
bEZlMHBqVlZiYVN3YXhoNllLaERFWTQKLS0tIEpUVVBnNTg3ZWs1T3Y2b2FWL0Ju
YzBYRHA0NW1YYUhCU1FNS2hjR1J0bm8KtDq8S+3d36IGEmP9sJhO+320F1Yij/LS
KWEjIdw2GNmrT47GxLdxrjlBVW1XRpfvXY0pY06aZekH+pbv0Ky9mA==
-----END AGE ENCRYPTED FILE-----
- recipient: age120530yclr75k6nrzp6k5jjftj8j4q9v3533guupzk4ct86mjxszqg9e5t5
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRZXU4WENzWkJrV0RsQ1Z1
eEVGY0gvTjRqZk5IdzluZVl2NkR5cVBodnlrCnVSNHFoUUwwYzkzcjAveHd2aTRU
Y1hxMVRCRnVBY0xvSUxPc3VYa0pQOFEKLS0tIE5LRlB2M1NWbmxVdU5QQWpOTFZR
akJRMzluN2FZV1BrRlNwTmpLTCtmZncKeoLK4tEzXoIu1bNESA2bsORNeYYFtLrW
flgLgR9JcoBnArZFFLEasW40qxPE2IFocoNJbnE1mMWHuMnupop01w==
-----END AGE ENCRYPTED FILE-----
- recipient: age1c4atxfp05u7zm875s6q8p82ve96rqqpq9smktxlur8pk2yc3qvgql46dp9
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxaUREZGJsb1lPdVdSeW1t
dHZWOCtPUEk0N1VVV250RU9QeFRHSFNrSEhnClJyRXZjYTB4YkpiVitlQXprK1Vs
WFpremRReFhjRlhCai9mOGdkRXVpMzQKLS0tIGZ2Zm5lVWZ3dHpWcVQrTzY2QStq
KzVKWStRQTY0SFJLcVdlTnVTbHNmYUkKWo4lRH1pLwGnuyfpt+C3N6k4ScLv7AK9
zf4hViJX7vQQuLTjuseWc3MJcER/8NlgCJnbpjTqxhBTfSVtezMQzA==
-----END AGE ENCRYPTED FILE-----
- recipient: age1rjldv3fn3q686647exmcukthr32gmp6s3axs0lhyenvru9ajp9rs24ukvz
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaRk9mN3o1MDNGMTNVUlJ6
TnREWW5PVzNYNXJWYU9JL09QOXpVK21UaDFnCmJGb0ZpWldaNWV1bDl5VFBqN0s0
OGJaZkZUREVjNDcvWUwrcHpDK0ZwM2sKLS0tIDhEUDZFL0tPTk1BblBEbnozTDBX
eUtDcEVCMHEwaXVvOUZQZ2sybERNaFEK/uCV+7pbXHIZwFSP8OgGYS8LvwqvcJEN
II383fqr0nzSQglNMiv0Xi7PE4pSaJoQ5zvcA8p75OEtlO+CJMzVSA==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-08-15T05:39:34Z"
mac: ENC[AES256_GCM,data:XZo74OLiKd11XE7uWeTt8al0ZQ2UwDTvj83hexPDAUm5zfKjJe+oiKj8o/Wcr0GGLwHGND/zHnHFLvfnVPzWldhL4gjHvHb8YUbmuXMEhOfssVABPASAs2YOzqUh4Qq65rRLQuGIkONA88IOTJzm9lcmqRr0n3I+FcWldBysN0I=,iv:XIsDkucbwCW7zQfipv86gJAnBQiF6ZPjq4bHGoMmQiU=,tag:B6s3Z8J50xUKxZ/iJOFDDw==,type:str]
pgp:
- created_at: "2025-08-15T05:38:28Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA82M54yws73UARAArAj1dN3BAbiezNZ3PAdY+0HGbkYSOZ4TsOpKGt0XynAK
/wK3jV314JYUNBkpopTAWN0idziV1bXVCpjuUBQlsCbjgxnWHfHnfpmrplOcBplJ
I6UUzq9M8Q1tex4NNH3sp2qPLMyLoc8AkaXgRWUzc1YfdRAjTHj9okUsYnctwuFM
IF+EOy6WqswFEu3g5eiMwqbUCQcj1GA1C6Zjs2mtrDmPgxvXuoByZhhTRN1qXqvG
GWdUeFRGQFzgHoUZgPPy7wOt6uZX/mKEpKrvKCkcglRFt7BYJCejJHKmxGi/JTMO
a2HMJAY04GQQ+w0aPdZcDxNoOeKNGpObKplpyS9iPulAbZWCqNb67Yo9web+tOB9
M2tTLggj4PSPP1SFeEjhFlWdJA/nWZGH3WPfojKSO3uJZf0rmeQXOVP68G0PAiyX
0AD1v6fvInnbPcXqSBbGIg29sGj0S/sMxQw9npprAK8RQdgVQghQRkPNTH6Mjtg0
uwzIONEg2vNSkvltwR+/tG3ILDeM4E7TaQKPHo2wuodhOOrsHxBjlGcgdazA/PMp
ypwrDmwpojrN02MkOxLip6MfRLP8qRQtDGIWUIZKUaAt3xMzgCyv1tEGhK0hiyTM
QgY+GFOsoJsqWaGYeJVH2FhUdV8dp2zfZYvhvLToYfyBdpQjvT9RABNcBGufUYzS
XgG3SUIkXe2NgyE7EPvngnMqtn9H4BOPl3h6bKtFPDjiKOsL+Ai+TBOxgOORQlrp
HXr12XC70RvRwvlNkF9rajLPeOn3RHsrBZDsJ1y89Waqllrv69lxwN46B8/Z39Y=
=11U7
-----END PGP MESSAGE-----
fp: CD8CE78CB0B3BDD4
unencrypted_suffix: _unencrypted
version: 3.10.2

View file

@ -23,7 +23,6 @@
};
};
ruleFiles = [
./synapse-v2.rules
];
scrapeConfigs = [
{
@ -38,14 +37,6 @@
}
];
}
{
job_name = "${config.networking.hostName}-minecraft";
static_configs = [
{
targets = ["127.0.0.1:25585"];
}
];
}
{
job_name = "${config.networking.hostName}";
static_configs = [
@ -101,15 +92,6 @@
}
];
}
{
job_name = "${config.networking.hostName}-synapse";
metrics_path = "/_synapse/metrics";
static_configs = [
{
targets = ["[::1]:8009"];
}
];
}
];
};
}

View file

@ -1,74 +0,0 @@
groups:
- name: synapse
rules:
###
### Prometheus Console Only
### The following rules are only needed if you use the Prometheus Console
### in contrib/prometheus/consoles/synapse.html
###
- record: 'synapse_federation_client_sent'
labels:
type: "EDU"
expr: 'synapse_federation_client_sent_edus_total + 0'
- record: 'synapse_federation_client_sent'
labels:
type: "PDU"
expr: 'synapse_federation_client_sent_pdu_destinations_count_total + 0'
- record: 'synapse_federation_client_sent'
labels:
type: "Query"
expr: 'sum(synapse_federation_client_sent_queries) by (job)'
- record: 'synapse_federation_server_received'
labels:
type: "EDU"
expr: 'synapse_federation_server_received_edus_total + 0'
- record: 'synapse_federation_server_received'
labels:
type: "PDU"
expr: 'synapse_federation_server_received_pdus_total + 0'
- record: 'synapse_federation_server_received'
labels:
type: "Query"
expr: 'sum(synapse_federation_server_received_queries) by (job)'
- record: 'synapse_federation_transaction_queue_pending'
labels:
type: "EDU"
expr: 'synapse_federation_transaction_queue_pending_edus + 0'
- record: 'synapse_federation_transaction_queue_pending'
labels:
type: "PDU"
expr: 'synapse_federation_transaction_queue_pending_pdus + 0'
###
### End of 'Prometheus Console Only' rules block
###
###
### Grafana Only
### The following rules are only needed if you use the Grafana dashboard
### in contrib/grafana/synapse.json
###
- record: synapse_storage_events_persisted_by_source_type
expr: sum without(type, origin_type, origin_entity) (synapse_storage_events_persisted_events_sep_total{origin_type="remote"})
labels:
type: remote
- record: synapse_storage_events_persisted_by_source_type
expr: sum without(type, origin_type, origin_entity) (synapse_storage_events_persisted_events_sep_total{origin_entity="*client*",origin_type="local"})
labels:
type: local
- record: synapse_storage_events_persisted_by_source_type
expr: sum without(type, origin_type, origin_entity) (synapse_storage_events_persisted_events_sep_total{origin_entity!="*client*",origin_type="local"})
labels:
type: bridges
- record: synapse_storage_events_persisted_by_event_type
expr: sum without(origin_entity, origin_type) (synapse_storage_events_persisted_events_sep_total)
- record: synapse_storage_events_persisted_by_origin
expr: sum without(type) (synapse_storage_events_persisted_events_sep_total)
###
### End of 'Grafana Only' rules block
###

View file

@ -0,0 +1,51 @@
{
self,
config,
lib,
...
}: let
inherit (lib.modules) mkOption;
inherit (lib.types) str nullOr;
inherit (lib.attrsets) filterAttrs mapAttrs;
enabledHosts = filterAttrs (_n: v: v.config.services.syncthing.enable) self.nixosConfigurations;
enabledSyncthings = mapAttrs (_n: _v: config.services.syncthing) enabledHosts;
enabledDevices = mapAttrs' (_n: v: (nameValuePair v.device_name {id = v.device_id;})) enabledSyncthings;
in {
options = {
services.syncthing = {
device_id = mkOption {
type = nullOr str;
default = null;
};
device_name = mkOption {
type = nullOr str;
default = config.networking.hostName;
};
};
};
config = {
sops.secrets = let
commonOptions = {
sopsFile = ./. + "${config.networking.hostName}.yaml";
};
in {
syncthing-key = commonOptions;
syncthing-cert = commonOptions;
};
services.syncthing = {
settings = {
devices = enabledDevices; # :3
};
extraFlags = ["--no-default-folder"];
# To those of us in future ages, including me going back over this,
# this is obtained via getting the contents of
# `syncthing generate --no-default-folder --config meep/`
# I hope this helps! That's what the content of those secrets are from.
key = sops.secrets.syncthing-key.path;
cert = sops.secrets.syncthing-cert.path;
};
};
}

View file

@ -1,13 +1,10 @@
{
config,
pkgs,
std,
inputs,
lib,
...
}: let
inherit (builtins) toJSON;
inherit (std) list set;
in {
home-manager.users.kat.programs.weechat = {
plugins = {

View file

@ -3,7 +3,8 @@
services.weechat.enable = true;
programs.weechat = {
enable = true;
config.weechat = { #with config.base16.defaultScheme.map.ansiStr; {
config.weechat = {
#with config.base16.defaultScheme.map.ansiStr; {
look = {
mouse = true;
separator_horizontal = "";

View file

@ -4,17 +4,38 @@
inherit (inputs.nixpkgs) lib;
overlay = import ./packages {inherit inputs tree;};
systems = import ./systems {inherit inputs tree lib std pkgs;};
shells = import ./shells {inherit inputs tree lib std pkgs;};
shells = import ./shells {inherit inputs tree lib std pkgs checks;};
inherit (import ./pkgs.nix {inherit inputs tree overlay;}) pkgs;
formatting = import ./formatting.nix {inherit inputs pkgs;};
inherit (std) set;
checks = set.map (_: deployLib: deployLib.deployChecks inputs.self.deploy) inputs.deploy-rs.lib;
forAllSystems = lib.genAttrs inputs.flake-utils.lib.defaultSystems;
checks = let
git-hooks = system:
inputs.git-hooks.lib.${system}.run {
src = ./.;
hooks = {
treefmt = {
enable = true;
packageOverrides = {treefmt = formatting.formatter.${system};};
};
flake-checker.enable = true;
ripsecrets.enable = true;
pre-commit-hook-ensure-sops.enable = true;
};
};
format = formatting.checks;
deploy = set.map (_: deployLib: deployLib.deployChecks inputs.self.deploy) inputs.deploy-rs.lib;
in
forAllSystems (system: {
deploy = deploy.${system};
format = format.${system};
git-hooks = git-hooks system;
});
in
{
inherit inputs tree std pkgs lib;
inherit inputs tree std pkgs lib checks;
legacyPackages = pkgs;
#packages = set.merge [pkgs wrappers.packages];
checks = checks // formatting.checks;
inherit (formatting) formatter;
}
// systems

View file

@ -10,7 +10,8 @@ SYSTEM_TYPE=${3:-""}
send_discord_message() {
local message="$1"
if [[ -n "$DISCORD_WEBHOOK_LINK" ]]; then
local escaped_message=$(printf '%s' "$message" | jq -R -s '.')
local escaped_message
escaped_message=$(printf '%s' "$message" | jq -R -s '.')
curl -s -H "Accept: application/json" -H "Content-Type: application/json" \
-X POST --data "{\"content\": $escaped_message}" "$DISCORD_WEBHOOK_LINK"
else

View file

@ -6,7 +6,8 @@ DISCORD_WEBHOOK_LINK=${DISCORD_WEBHOOK_LINK:-""}
# Helper functions
send_discord_message() {
local message="$1"
local escaped_message=$(printf '%s' "$message" | jq -R -s '.')
local escaped_message
escaped_message=$(printf '%s' "$message" | jq -R -s '.')
curl -s -H "Accept: application/json" -H "Content-Type: application/json" \
-X POST --data "{\"content\": $escaped_message}" "$DISCORD_WEBHOOK_LINK"
}
@ -47,7 +48,7 @@ if [[ -n ${NF_UPDATE_CACHIX_PUSH-} && -v NF_ACTIONS_TEST_OUTLINK ]]; then
fi
if [[ -z ${NF_UPDATE_GIT_COMMIT-} ]]; then
wait ${CACHIX_PUSH-}
wait "${CACHIX_PUSH-}"
exit
fi
@ -63,8 +64,8 @@ env \
git commit --message="chore(ci): flake update"
if [[ ${GITHUB_REF-} = refs/heads/${NF_UPDATE_BRANCH-main} ]]; then
git push origin HEAD:${NF_UPDATE_BRANCH-main}
git push origin "HEAD:${NF_UPDATE_BRANCH-main}"
send_discord_message "Pushed a new commit!"
fi
wait ${CACHIX_PUSH-}
wait "${CACHIX_PUSH-}"

View file

@ -0,0 +1,15 @@
{
lib,
linuxPackages,
bc,
writeShellScriptBin,
}: let
inherit (lib) makeBinPath;
in
writeShellScriptBin "nvidia-vram" ''
export PATH="$PATH:${lib.makeBinPath [
linuxPackages.nvidia_x11
bc
]}"
exec ${./nvidia-vram.sh} "$@"
''

View file

@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -euo pipefail
SMI_OUTPUT="$(nvidia-smi --query-gpu=memory.used,memory.total --format=csv,noheader,nounits)"
echo "$SMI_OUTPUT" | while IFS=", " read -r usedvmem totalvmem
do
PERCENTAGE=$(echo "scale=1; (${usedvmem} / ${totalvmem}) * 100" | bc)
echo "${usedvmem}/${totalvmem}MiB (${PERCENTAGE}%)"
done

View file

@ -1,158 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Configuration
HOMESERVER=${HOMESERVER:-""}
API_ID=${API_ID:-""}
DISCORD_WEBHOOK_LINK=${DISCORD_WEBHOOK_LINK:-""}
TEMPDIR=$(mktemp -d)
MONTHS_TO_KEEP=1
# Helper functions
send_discord_message() {
local message="$1"
echo "$message"
local escaped_message=$(printf '%s' "$message" | jq -R -s '.')
curl -s -H "Accept: application/json" -H "Content-Type: application/json" \
-X POST --data "{\"content\": $escaped_message}" "$DISCORD_WEBHOOK_LINK"
}
get_db_size() {
sudo -u postgres psql matrix-synapse -t -c \
"SELECT pg_size_pretty(pg_database_size('matrix-synapse'));" | tr -d ' '
}
get_media_store_size() {
sudo du /var/lib/matrix-synapse/media_store -hd 0 | awk '{print $1}'
}
get_filesystem_usage() {
df -h / | awk 'NR==2 {print $5 " (" $3 ")"}' | tr -d '\n'
}
calculate_ratio() {
local before="$1"
local after="$2"
awk "BEGIN {printf \"%.2f\", ($after / $before) * 100}"
}
# Main script
main() {
# Check for required variables
if [[ -z "$HOMESERVER" || -z "$API_ID" || -z "$DISCORD_WEBHOOK_LINK" ]]; then
send_discord_message "Error: HOMESERVER, API_ID, and DISCORD_WEBHOOK_LINK must be set."
exit 1
fi
# Initial sizes and usage
local db_before_size=$(get_db_size)
local media_before_size=$(get_media_store_size)
local fs_before_usage=$(get_filesystem_usage)
send_discord_message "Beginning matrix-synapse optimization process - Database before size: ${db_before_size}, Media store before size: ${media_before_size}, Filesystem usage before: ${fs_before_usage}"
send_discord_message "Starting synapse"
systemctl start matrix-synapse
sleep 5
send_discord_message "Collecting required room data"
curl --header "Authorization: Bearer ${API_ID}" \
"https://${HOMESERVER}/_synapse/admin/v1/rooms?limit=500" > "${TEMPDIR}/roomlist.json"
jq '.rooms[] | select(.joined_local_members == 0) | .room_id' < "${TEMPDIR}/roomlist.json" > "${TEMPDIR}/to_purge.txt"
jq -c '.rooms[] | select(.joined_local_members != 0) | .room_id' < "${TEMPDIR}/roomlist.json" > "${TEMPDIR}/history_purge.txt"
local ts=$(( $(date --date="${MONTHS_TO_KEEP} month ago" +%s)*1000 ))
send_discord_message "Cleaning up media store"
curl --header "Authorization: Bearer ${API_ID}" -X POST \
"https://${HOMESERVER}/_synapse/admin/v1/media/delete?before_ts=${ts}&include_local=true"
send_discord_message "Deleting empty rooms"
while read -r room_id; do
if [ -n "${room_id}" ]; then
curl --header "Authorization: Bearer ${API_ID}" -X DELETE \
-H "Content-Type: application/json" -d "{}" \
"https://${HOMESERVER}/_synapse/admin/v2/rooms/${room_id}"
fi
done < "${TEMPDIR}/to_purge.txt"
send_discord_message "Deleting unnecessary room history"
while read -r room_id; do
room_id=$(echo "$room_id" | tr -d '"') # Remove quotes if present
if [ -n "${room_id}" ]; then
curl --header "Authorization: Bearer ${API_ID}" -X POST \
-H "Content-Type: application/json" \
-d "{ \"delete_local_events\": true, \"purge_up_to_ts\": ${ts} }" \
"https://${HOMESERVER}/_synapse/admin/v1/purge_history/${room_id}"
fi
done < "${TEMPDIR}/history_purge.txt"
send_discord_message "Performing database optimization"
systemctl stop matrix-synapse
export PGHOST=/var/run/postgresql/
export PGDATABASE=matrix-synapse
export PGUSER=matrix-synapse
sudo -u postgres psql matrix-synapse <<_EOF
BEGIN;
DELETE
FROM state_compressor_state AS scs
WHERE NOT EXISTS
(SELECT *
FROM rooms AS r
WHERE r.room_id = scs.room_id);
DELETE
FROM state_compressor_state AS scs
WHERE scs.room_id in
(SELECT DISTINCT room_id
FROM state_compressor_state AS scs2
WHERE scs2.current_head IS NOT NULL
AND NOT EXISTS
(SELECT *
FROM state_groups AS sg
WHERE sg.id = scs2.current_head));
DELETE
FROM state_compressor_progress AS scp
WHERE NOT EXISTS
(SELECT *
FROM state_compressor_state AS scs
WHERE scs.room_id = scp.room_id);
COMMIT;
_EOF
send_discord_message "Running synapse_auto_compressor"
sudo -u matrix-synapse synapse_auto_compressor \
-p "postgresql://matrix-synapse?user=matrix-synapse&host=/var/run/postgresql/" \
-c 500 -n 100
send_discord_message "Reindexing database"
sudo -u postgres psql matrix-synapse -c "REINDEX (VERBOSE) DATABASE \"matrix-synapse\";"
send_discord_message "Vacuuming database"
sudo -u postgres psql matrix-synapse -c "VACUUM FULL VERBOSE;"
rm -rf "${TEMPDIR}"
send_discord_message "Synapse cleanup performed, booting up"
systemctl start matrix-synapse
# Final sizes, usage, and ratios
local db_after_size=$(get_db_size)
local media_after_size=$(get_media_store_size)
local fs_after_usage=$(get_filesystem_usage)
local db_ratio=$(calculate_ratio "${db_before_size//[A-Za-z]/}" "${db_after_size//[A-Za-z]/}")
local media_ratio=$(calculate_ratio "${media_before_size//[A-Za-z]/}" "${media_after_size//[A-Za-z]/}")
send_discord_message "Matrix-synapse optimization process finished -
Database: ${db_before_size} -> ${db_after_size} (${db_ratio}%),
Media store: ${media_before_size} -> ${media_after_size} (${media_ratio}%),
Filesystem usage: ${fs_before_usage} -> ${fs_after_usage}"
}
# Run the main function
main

View file

@ -1,15 +0,0 @@
{
wrapShellScriptBin,
pkgs,
}:
wrapShellScriptBin "synapse-cleanup" ./cleanup.sh {
depsRuntimePath = with pkgs; [
matrix-synapse-tools.rust-synapse-compress-state
curl
gawk
sudo
postgresql
rink
jq
];
}

View file

@ -5,16 +5,16 @@
std,
pkgs,
...
}: let
} @ argy: let
inherit (std) set;
in
inputs.flake-utils.lib.eachDefaultSystem (system: {
devShells = let
shells = set.map (_: path:
import path {
inherit tree inputs system lib std;
import path (argy
// {
pkgs = pkgs.${system};
})
}))
tree.shells;
in
shells // {default = shells.repo;};

View file

@ -1,15 +1,14 @@
{
pkgs,
inputs,
std,
checks,
...
}:
with pkgs; let
repo = import ../outputs.nix {inherit inputs;};
inherit (std) set;
systemless-git-hooks = system: inputs.self.checks.${system}.git-hooks;
git-hooks = systemless-git-hooks pkgs.system;
repoShell = mkShell {
nativeBuildInputs =
[
nativeBuildInputs = [
nf-build-system
nf-update
lix
@ -20,12 +19,10 @@ with pkgs; let
alejandra # code formatter
statix # anti-pattern finder
deploy-rs.deploy-rs # deployment system
]
++ set.values (set.map (name: _: (pkgs.writeShellScriptBin "${name}-rebuild" ''
${pkgs.darwin-rebuild}/bin/darwin-rebuild switch --flake $REPO_ROOT#${name} $@
''))
repo.darwinConfigurations);
];
inherit (git-hooks) buildInputs;
shellHook = ''
${git-hooks.shellHook}
export CI_PLATFORM="impure"
echo -e "\e[39m\e[1m$USER@$REPO_HOSTNAME - \e[35m''$(realpath --relative-to=../ ./nixos/)\e[0m"
'';

View file

@ -1,5 +1,5 @@
{ lib, pkgs, ... }: let
inherit (lib.modules) mkForce;
{lib, ...} @ specyArgs: let
inherit (lib.attrsets) removeAttrs;
hostConfig = {
tree,
modulesPath,
@ -9,6 +9,10 @@
[
(modulesPath + "/profiles/qemu-guest.nix")
]
++ (with tree.nixos; [
container-host
microvm-host
])
++ (with tree.nixos.profiles; [
server
])
@ -22,6 +26,29 @@
web
]);
# TODO: Add config.microvm.stateDir to backup schedule?
# TODO: figure out updateFlake?
microvm = {
host.enable = true;
vms = {
syncthing = {
autostart = true;
specialArgs = removeAttrs specyArgs ["config" "pkgs" "lib"];
config = {
imports = [
tree.nixos.servers.syncthing
];
services = {
syncthing = {
enable = true;
};
};
};
restartIfChanged = true;
};
};
};
system.stateVersion = "23.11";
};
in {

View file

@ -8,7 +8,6 @@ _: let
...
}: let
inherit (lib.attrsets) nameValuePair listToAttrs;
inherit (lib.meta) getExe';
datasets = [
"root"
"nix"
@ -98,14 +97,24 @@ _: let
];
};
waybar.settings.main = {
modules-center = [
modules-right = [
"custom/nvidia-vram"
];
"custom/nvidia-vram" = {
tooltip = false;
format = "nvidia {}";
format = "vram {}";
interval = 1;
exec = "${getExe' config.hardware.nvidia.package "nvidia-smi"} --query-gpu=memory.used,memory.total,pstate --format=csv,noheader,nounits";
exec = let
inherit (lib.meta) getExe;
inherit (pkgs) writeShellScriptBin bc;
nvidia-vram = writeShellScriptBin "nvidia-vram" ''
export PATH="$PATH:${lib.makeBinPath [
config.hardware.nvidia.package
bc
]}"
exec ${../packages/nvidia-vram/nvidia-vram.sh} "$@"
'';
in "${getExe nvidia-vram}";
return-type = "";
};
};
@ -113,6 +122,16 @@ _: let
outputs = {
"LG Electronics LG Ultra HD 0x0001AC91" = {
scale = 1.0;
position = {
x = 1920;
y = 0;
};
};
"Samsung Electric Company SAMSUNG Unknown" = {
position = {
x = 0;
y = 0;
};
};
"PNP(XXX) Beyond TV 0x00010000" = {
mode = {
@ -167,7 +186,6 @@ _: let
'';
};
services.xserver.videoDrivers = ["nvidia"];
hardware.nvidia = {

View file

@ -1,6 +1,7 @@
export DAIYOUSEI_IPV4="$(terraform output --raw daiyousei_public_ipv4)"
export MEI_IPV4="$(terraform output --raw mei_public_ipv4)"
export MAI_IPV4="$(terraform output --raw mai_public_ipv4)"
#!/usr/bin/env bash
DAIYOUSEI_IPV4="$(terraform output --raw daiyousei_public_ipv4)"
MEI_IPV4="$(terraform output --raw mei_public_ipv4)"
MAI_IPV4="$(terraform output --raw mai_public_ipv4)"
echo "Daiyousei - Flex: ${DAIYOUSEI_IPV4}"
echo "Mei - Micro: ${MEI_IPV4}"

View file

@ -92,6 +92,7 @@
nixos-cli.nixosModules.nixos-cli
nix-flatpak.nixosModules.nix-flatpak
stylix.nixosModules.stylix
microvm.nixosModules.host
];
};
};

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