Compare commits
617 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ccbd2362b2 | |||
| 9b85f9edd5 | |||
| 459ad6081b | |||
| 1c1ba8b776 | |||
| f76b350d94 | |||
| 25ad6502fc | |||
| ba8c0bdf3d | |||
| c161673102 | |||
| 6929369c28 | |||
| ee4ab0e8a6 | |||
| f7108a173a | |||
| 0a3f0ada27 | |||
| 74699ff880 | |||
| 1b5cf2cf39 | |||
| a4f0cbb017 | |||
| 6b5dedb3e6 | |||
| 2f11bf580d | |||
| f58cd9a516 | |||
| 7bf2c6fea2 | |||
| ba09321f6b | |||
| 7d938288ab | |||
| 9f16735547 | |||
| 19a4870450 | |||
| f33330b2d6 | |||
| 2de8603b49 | |||
| 13524322a2 | |||
| ecb13d8b19 | |||
| 3558d604eb | |||
| fffe6bc7cc | |||
| 1c71784ac9 | |||
| dca67e19bc | |||
| 4a9aa15b77 | |||
| 86f044235a | |||
| 5b6477cab6 | |||
| c86358010c | |||
| 318718aabd | |||
| d592750de7 | |||
| 688f8e8a1e | |||
| c986952c50 | |||
| d914905d01 | |||
| 784e44901d | |||
| 35707279b4 | |||
| 4fb3325326 | |||
| ae3a43d25d | |||
| acadd94b31 | |||
| 7cadace240 | |||
| f097c9e15f | |||
| 9b5134c32d | |||
| e39f5d46ff | |||
| b21bcf5e7a | |||
| 0bb78842c0 | |||
| d148acd6dd | |||
| 00011ed365 | |||
| 54737695af | |||
| ac3232ac80 | |||
| 5bb996c93f | |||
| 8a7b475562 | |||
| dccc191c24 | |||
| 25477c0f7c | |||
| 6351495541 | |||
| 428488f11d | |||
| f8e843ec94 | |||
| 679f2e8f6b | |||
| 9aae7d6df9 | |||
| c6cd00f955 | |||
| 33cb851539 | |||
| 5ec7f5edc7 | |||
| e7e5226c87 | |||
| b550064a15 | |||
| 9ff47e94b2 | |||
| 3dc170984b | |||
| 97a23a26dd | |||
| da383a3526 | |||
| ad8b59f314 | |||
| cfcf9d6f3a | |||
| 44af726a53 | |||
| 35f810dcf1 | |||
| af331d967a | |||
| d54fa4e999 | |||
| 0197c58ea1 | |||
| 1b4cfbe350 | |||
| c4ed00e6c8 | |||
| b720c1ff02 | |||
| 9ee5f40aa8 | |||
| 2ef1d58ea7 | |||
| 7281eedf56 | |||
| 8394a4cf35 | |||
| f50c57c7b2 | |||
| 795a7babd0 | |||
| 97d50851f6 | |||
| 870c8d2df3 | |||
| 80e38516a6 | |||
| 04627242a8 | |||
| bcad6c2f69 | |||
| 0940fd31d7 | |||
| 9fc1763073 | |||
| 3d51e1db83 | |||
| 992ca558dd | |||
| 72c94dbd63 | |||
| 0a4bfdfab8 | |||
| cfbc56ab6d | |||
| 516fe436e6 | |||
| 373f3f1f3f | |||
| 283f572371 | |||
| 272b5b8545 | |||
| f345fef540 | |||
| dd9281dcf1 | |||
| 14b873d704 | |||
| a793429622 | |||
| d9f848f626 | |||
| 2d77a5d42e | |||
| 8d01f300be | |||
| 975b2c2002 | |||
| f28ed60390 | |||
| 63becaaa09 | |||
| 78f6ede871 | |||
| d34494d3be | |||
| 7930757d88 | |||
| f3517d04fc | |||
| 5edc88fc23 | |||
| 461b1099ad | |||
| 51a35355df | |||
| cc681ffe91 | |||
| 45213f1f7d | |||
| 27f52450c3 | |||
| 4bfc554e35 | |||
| 2558f4a9b0 | |||
| 4e882084b1 | |||
| aa28cf999f | |||
| 4a911de198 | |||
| a4f5cddcb2 | |||
| bd75285889 | |||
| d263ea39f8 | |||
| 002799deee | |||
| 6f884ad114 | |||
| 1f3c44afb7 | |||
| 7bc837aeaf | |||
| cd440d2b00 | |||
| 5e3902c22c | |||
| 7280b68f14 | |||
| 2b9067f87b | |||
| 7fd73ba79e | |||
| 00f6c9840b | |||
| 8da1baea93 | |||
| 75d5fc850e | |||
| 283f6cd29f | |||
| d3d9371e71 | |||
| eec7fe5808 | |||
| 683ceefae3 | |||
| b8f28a6277 | |||
| 73aab2452e | |||
| 109fdb4672 | |||
| 6281f9ea6f | |||
| edfb269308 | |||
| eed84ec64c | |||
| ae7d017d2b | |||
| e17b21ab69 | |||
| 59d29c6cea | |||
| 29792a1307 | |||
| b86df062df | |||
| b02be43aa0 | |||
| 6d19db6577 | |||
| e8f35bf283 | |||
| ec1e9a9b59 | |||
| f1fede7cd5 | |||
| 9d3ba797d7 | |||
| 39b190fcc3 | |||
| b8df78e935 | |||
| 425c429297 | |||
| c656cf81d2 | |||
| 2ed2e28ba2 | |||
| daa3ed6eef | |||
| c640e5514e | |||
| 796e311a29 | |||
| 5fe83ddc8a | |||
| 6167ca3d0a | |||
| 10374ba152 | |||
| f20d6fbe83 | |||
| 4bb65bd5ec | |||
| 214f709b59 | |||
| ae76a1b13b | |||
| f4a2d28806 | |||
| 483bd73ecd | |||
| 3bb0844544 | |||
| 137576a9a9 | |||
| ac265015eb | |||
| bb97da851d | |||
| 3b33aec48b | |||
| 1694a23bf6 | |||
| 62a99d8992 | |||
| 1d28b04845 | |||
| 31a9de7979 | |||
| 863d91a0f8 | |||
| 69a6571d5b | |||
| 80ea4c9e55 | |||
| c82d3872a1 | |||
| d061d30426 | |||
| 15b2c36247 | |||
| 5443027e94 | |||
| 8fbfe2f011 | |||
| 31a2d191f9 | |||
| 5788ef1bcd | |||
| 354db486bf | |||
| bcf913e431 | |||
| 973d32228d | |||
| f6afc23771 | |||
| 1ed219c697 | |||
| 39aa8a421e | |||
| 40efab98b9 | |||
| aaa635f25e | |||
| 7a5c811ec7 | |||
| b656898f48 | |||
| aa7d9964a6 | |||
| da45e673af | |||
| e87d4207b2 | |||
| 897908da86 | |||
| 404f272d83 | |||
| e0a6aa12e8 | |||
| 77583b9c8f | |||
| d667dbdb91 | |||
| a2acedf2bb | |||
| b398d5b797 | |||
| fc0c7d9405 | |||
| 7d8f6ad78e | |||
| bb77bb6ab8 | |||
| a9aed4b7c8 | |||
| a6641d71d7 | |||
| c016d3ba66 | |||
| 18e67e1c4c | |||
| 6b3662c07c | |||
| bf279b426e | |||
| 5b541fc4ad | |||
| ec70617dc2 | |||
| 321dbbe979 | |||
| b62e4cbafb | |||
| 39fb2b4d27 | |||
| 0327caa6d2 | |||
| d224b12bab | |||
| fdcabbe543 | |||
| 26e597e087 | |||
| 7bdc88389b | |||
| 237a7996f5 | |||
| a85014188f | |||
| f2f44f2fdd | |||
| d71be6d7d9 | |||
| 2cfa182da2 | |||
| 36bc769452 | |||
| 4e9d47a886 | |||
| e73d9477f7 | |||
| 906ce21aaa | |||
| 588f1a17ca | |||
| 8a9569bb76 | |||
| 6e9949ac39 | |||
| 74446a9e81 | |||
| 89d9c151c5 | |||
| fcfe6e6493 | |||
| 475c870c37 | |||
| 6eef6108c4 | |||
| 6919f27890 | |||
| 33d80a34bb | |||
| 83919d2367 | |||
| bc6dae065b | |||
| 0fb7553ebf | |||
| ad6a4b0021 | |||
| df56ff3579 | |||
| 8c225a381d | |||
| 4c80538ee4 | |||
| 055a57d005 | |||
| 513daff499 | |||
| 3a146f39b7 | |||
| 7278086b82 | |||
| 0e7568b746 | |||
| 3d317b672d | |||
| 9593f16875 | |||
| 8ae15e1149 | |||
| 91a70ee052 | |||
| 874d2cbf25 | |||
| 9827078e36 | |||
| 3b1f775129 | |||
| 940fb3ed2e | |||
| 51685d59f2 | |||
| 25f838b454 | |||
| 49ea478d57 | |||
| fa39d60ded | |||
| 71cf63c461 | |||
| 161c6337a4 | |||
| d74fa4e552 | |||
| 92a3fef81b | |||
| d009ca3d3a | |||
| 6696db16ab | |||
| 1a48e22c9d | |||
| ac55b09c68 | |||
| 4592a9cda0 | |||
| 0e446fa4bd | |||
| dfbd9950d6 | |||
| cc9df9f425 | |||
| 8451c0e844 | |||
| 47de61c982 | |||
| d4be82176d | |||
| ca7968ae14 | |||
| 4412cd119d | |||
| 1db6f4dddd | |||
| d30bfc951e | |||
| 6694ed268a | |||
| eed6bfd51b | |||
| b6aa962496 | |||
| 98fb607238 | |||
| 9190eb6281 | |||
| c85cdcf54d | |||
| 68da7615ee | |||
| 95b71a562f | |||
| 62e5b210e4 | |||
| d28ef117fa | |||
| e96f291048 | |||
| d3b073fda4 | |||
| 1a3559b9c0 | |||
| d662e5dcc7 | |||
| 59340e4d6d | |||
| 34a0243c43 | |||
| 3dc1fa61e0 | |||
| 1fd59ceb04 | |||
| 66adb9d1d6 | |||
| 27c471addd | |||
| 3f5f2fbcd6 | |||
| 7d04d1d840 | |||
| f8cdd03c17 | |||
| 3b35cc12d3 | |||
| 08b78610f3 | |||
| 32cf771c69 | |||
| 16b7b342d1 | |||
| a78fdfcaeb | |||
| a5e9acad20 | |||
| c47e115020 | |||
| a92d654fe0 | |||
| 57333f3a73 | |||
| 32cd6760b6 | |||
| 999710d44c | |||
| 938c244704 | |||
| 6ab0623c55 | |||
| fa543b059f | |||
| 780afcbda6 | |||
| 9b3b09f6e5 | |||
| a234c2d573 | |||
| 602acee708 | |||
| cb9c91c7a7 | |||
| 4d9d68e7e6 | |||
| 3aad507ba8 | |||
| 1cd2b54e6a | |||
| 8372715482 | |||
| eb10aa526e | |||
| e8abbff15e | |||
| b9471c83ed | |||
| 46c08d95ec | |||
| f302399b70 | |||
| c9387525eb | |||
| c1a76f2b2b | |||
| ef68c8191e | |||
| 16a14f9863 | |||
| 10cb0370b6 | |||
| 5bf24e41fb | |||
| af2a4738a8 | |||
| 20e39113a9 | |||
| f5d81a5a43 | |||
| 39f692919b | |||
| fed7db4fbc | |||
| 9fa7d0c4f5 | |||
| d1a3e369e4 | |||
| ab9247bc45 | |||
| 4b1d5c5f02 | |||
| fe39db683a | |||
| 5fa73c0bad | |||
| 8231d88a5b | |||
| b9595f283a | |||
| 4cf1c3e74d | |||
| a97d65ac0e | |||
| 5e905af198 | |||
| f113b5d9b8 | |||
| 4ce7ab874f | |||
| 2049c94a1c | |||
| 2e14ccbe1a | |||
| 80190502ba | |||
| 6ca530741e | |||
| 3505aabbc7 | |||
| c124898b8c | |||
| e3bac0adc6 | |||
| af1ae030a4 | |||
| f0b48b9f61 | |||
| 8f6dc9796d | |||
| a9f2e86491 | |||
| 8ac3c21228 | |||
| cf2f942f0b | |||
| 0ac2ceba5c | |||
| b241a5c5f4 | |||
| 69154e639a | |||
| 6e8c747a5c | |||
| e753361e07 | |||
| d96148bf06 | |||
| 2d9f95e8e5 | |||
| c604816aa9 | |||
| cf28f0cede | |||
| 22fc29f8f1 | |||
| 51419d6171 | |||
| 37dde66dc4 | |||
| fa1baa128f | |||
| ad64748ad7 | |||
| 381c4876d9 | |||
| 06383737d7 | |||
| 069e53d66f | |||
| 00ea547c8d | |||
| aa7e045303 | |||
| f9ab7268d2 | |||
| 9e49f7f433 | |||
| 6621b7aa7b | |||
| bd5f8eec2b | |||
| 11b4f2410d | |||
| 4c0fe82453 | |||
| 830165aab8 | |||
| 93e5181cb6 | |||
| 7d5a24c7f8 | |||
| 882063c6c6 | |||
| 7fe00a1375 | |||
| 6d0963827b | |||
| 74bef0c5cd | |||
| 684ee6f23d | |||
| 3135e1cec4 | |||
| be4b66fdd2 | |||
| 8b66ff719b | |||
| edfa915586 | |||
| 3980c8ae88 | |||
| 348d2b46e6 | |||
| a4f41a0371 | |||
| 7cd5b88c45 | |||
| bf3e18d17c | |||
| 7af0cfd06d | |||
| 6628c4d589 | |||
| 260ca708a8 | |||
| ef7c3d23a3 | |||
| c2cb932c66 | |||
| 21b805741f | |||
| 44fa744312 | |||
| 445f70a5ec | |||
| eb9d3f2d16 | |||
| 66f6ae06d7 | |||
| 08868fc241 | |||
| 811011d6d6 | |||
| 7df49ad646 | |||
| 2caa21482f | |||
| 573231b99a | |||
| 04190ab15c | |||
| 63832528f2 | |||
| 18a687f114 | |||
| e0edcb77e1 | |||
| 9795d54dd4 | |||
| fd28c24d7a | |||
| e05f9d387e | |||
| 0ad80cf7a1 | |||
| c4639d88c5 | |||
| e4e90059e3 | |||
| 07879586b4 | |||
| 2d3ec51eb1 | |||
| 88eaa7a242 | |||
| 5faef18601 | |||
| c9d7932bda | |||
| 7ebc2f366b | |||
| 69b3d42f9a | |||
| 587266c904 | |||
| ded05e23fc | |||
| 07d33b60dc | |||
| cd647e7d7b | |||
| facce75d9f | |||
| ab6eb6db5b | |||
| a036da9b76 | |||
| b796260c7e | |||
| 4a23455792 | |||
| bbe6ef38b7 | |||
| 3b7ed586c6 | |||
| f9c11e0dc0 | |||
| 5e093d351b | |||
| 2c88a52d5a | |||
| b55c662a1b | |||
| 73b5b2c9f6 | |||
| f155563ca0 | |||
| 9b615f3825 | |||
| 56a829cdb3 | |||
| d7c275f6e9 | |||
| 420d4f173c | |||
| ec424cd6d8 | |||
| fc765ee94f | |||
| b86646816b | |||
| 12dbe7536f | |||
| 1bbac664e7 | |||
| e5a5189158 | |||
| fa0e502472 | |||
| 562d1f30e4 | |||
| b86499aec5 | |||
| 1fdfb9f62a | |||
| 2b6a99b191 | |||
| 454673329f | |||
| a4e661d6ad | |||
| dc38c2d88a | |||
| c267da0953 | |||
| c5e76b1a44 | |||
| 335d41cf19 | |||
| 4360edef9e | |||
| fde813460a | |||
| 7a6e450c8f | |||
| 59656b7dc8 | |||
| f18f33c9c3 | |||
| 10c6f094f6 | |||
| a6fdaf9a27 | |||
| 1b8e5032f9 | |||
| aaef1dccb2 | |||
| 21a61f528b | |||
| 7ab78044b7 | |||
| 28e9c06ea8 | |||
| 960ac31702 | |||
| f6b1976809 | |||
| f6156cad67 | |||
| 88b4ff68a6 | |||
| a4e2cf06e9 | |||
| 67fa3f06ed | |||
| 20930ea6c2 | |||
| deb4749489 | |||
| 96b228aadc | |||
| 2dc8180d1b | |||
| dd1213c5b7 | |||
| 47bd23b3dd | |||
| 25bba64185 | |||
| ffdb003aa2 | |||
| d3c0b74ab5 | |||
| c9b98978fa | |||
| 7cec25fdb9 | |||
| 446cfea7dd | |||
| 3fd62d4525 | |||
| 69253992df | |||
| 35845cac3a | |||
| 33c6170c15 | |||
| dd36c2711a | |||
| e9c69c2cc1 | |||
| 30fbcec7f5 | |||
| c0f21fa798 | |||
| cb61d6ad3d | |||
| 7588100a62 | |||
| 5ce6b68252 | |||
| 5a6cdb3171 | |||
| dcf30faa51 | |||
| 3096697e35 | |||
| cdce0628ab | |||
| 1c82b5eafe | |||
| 216011d9f6 | |||
| 73a837925b | |||
| 47258d9e4d | |||
| 8ae075d84c | |||
| 6e4fe781ab | |||
| dfbdf1cd87 | |||
| f947721819 | |||
| c3fdb180ff | |||
| e1b503b43b | |||
| a46fa6344d | |||
| 2ab60c6047 | |||
| 2a3c6ae6a9 | |||
| 0181c007fe | |||
| 83cdb81173 | |||
| 2580cf8aa5 | |||
| de8e083e92 | |||
| 49460feb44 | |||
| 4768918d0d | |||
| a534ad610f | |||
| 4015222d6a | |||
| b23774d0a2 | |||
| 58c1860ecf | |||
| 302c5e11b2 | |||
| 757d9e523d | |||
| 673d824c26 | |||
| 8355d35aaf | |||
| 1601f4b622 | |||
| ee5165b068 | |||
| 76138fc342 | |||
| 2f1b33d070 | |||
| bde12c7a04 | |||
| 658d489fd5 | |||
| 95f95e208d | |||
| b5eb134f69 | |||
| 6264269817 | |||
| 8151c56cc4 | |||
| 3a75206afb | |||
| b5a542a37c | |||
| bd2465d356 | |||
| e5bc8801a4 | |||
| c97a5887df | |||
| ec55ac55b2 | |||
| 65f04a69ae | |||
| ad40c37d1e | |||
| 4f3fe9be8b | |||
| 6f3c0e8f6c | |||
| 481fb8c6c4 | |||
| 94f5d8ba01 | |||
| ea18baa039 | |||
| 1653fe3eb2 | |||
| 162321eb28 | |||
| d947870a55 | |||
| 6550d6e871 | |||
| 352f2d923b | |||
| e10deb6ae5 | |||
| 90123ac18d | |||
| 1bd3096d53 | |||
| ca68b1de73 | |||
| f8386beb6c | |||
| b9f125e76a | |||
| 3717ecc642 | |||
| 377cd79704 | |||
| fea33ada52 | |||
| a4cf2833bc | |||
| 8491971427 | |||
| b4f4b67a8b | |||
| f59110c87e | |||
| 3dd4f2783e |
@@ -0,0 +1,88 @@
|
||||
---
|
||||
name: code-cleaner
|
||||
description: Use this agent when code needs to be organized, refactored for clarity, or cleaned of redundancies. This includes situations where: duplicate code blocks exist, imports are disorganized or unused, variable names are inconsistent, code structure is messy or hard to follow, dead code needs removal, or files need general tidying after feature implementation.\n\nExamples:\n\n<example>\nContext: The user has just finished implementing a feature with multiple utility functions.\nuser: "I've added the user authentication feature with password validation"\nassistant: "I've implemented the authentication feature. Now let me use the code-cleaner agent to organize the code and remove any redundancies."\n<commentary>\nAfter implementing a feature, use the code-cleaner agent to ensure the code is well-organized and free of duplication.\n</commentary>\n</example>\n\n<example>\nContext: The user notices their codebase has become messy over time.\nuser: "This file has gotten really messy, can you clean it up?"\nassistant: "I'll use the code-cleaner agent to organize this file and eliminate any redundancies."\n<commentary>\nWhen explicitly asked to clean or organize code, delegate to the code-cleaner agent for thorough refactoring.\n</commentary>\n</example>\n\n<example>\nContext: The user has merged multiple branches and the code has duplicate implementations.\nuser: "After merging those branches, I think we have some duplicate helper functions"\nassistant: "I'll launch the code-cleaner agent to identify and consolidate the duplicate implementations."\n<commentary>\nWhen duplicate code is suspected or known to exist, use the code-cleaner agent to find and eliminate redundancies.\n</commentary>\n</example>
|
||||
model: sonnet
|
||||
color: green
|
||||
---
|
||||
|
||||
You are an elite Code Cleaner—a meticulous software craftsman specializing in code organization, refactoring, and the elimination of redundancies. You have an exceptional eye for identifying patterns, inconsistencies, and opportunities to simplify without changing functionality.
|
||||
|
||||
## Your Core Mission
|
||||
Transform messy, redundant, or disorganized code into clean, maintainable, and elegant implementations while preserving exact functionality.
|
||||
|
||||
## Operational Principles
|
||||
|
||||
### 1. Analysis First
|
||||
Before making any changes:
|
||||
- Read and understand the complete context of the code
|
||||
- Identify all redundancies, duplications, and organizational issues
|
||||
- Map dependencies to ensure changes won't break functionality
|
||||
- Document what you plan to change and why
|
||||
|
||||
### 2. Types of Cleaning You Perform
|
||||
|
||||
**Import Organization:**
|
||||
- Remove unused imports
|
||||
- Group imports logically (standard library, third-party, local)
|
||||
- Sort imports alphabetically within groups
|
||||
- Consolidate multiple imports from the same module
|
||||
|
||||
**Redundancy Elimination:**
|
||||
- Identify and consolidate duplicate code blocks into reusable functions
|
||||
- Remove dead code (unreachable code, commented-out blocks, unused variables)
|
||||
- Simplify overly complex conditional chains
|
||||
- Eliminate redundant type conversions or operations
|
||||
|
||||
**Code Structure:**
|
||||
- Organize functions/methods in logical order (public before private, related functions grouped)
|
||||
- Ensure consistent indentation and spacing
|
||||
- Break up overly long functions into smaller, focused units
|
||||
- Move misplaced code to appropriate locations
|
||||
|
||||
**Naming Consistency:**
|
||||
- Standardize naming conventions throughout the file
|
||||
- Rename unclear variables to be more descriptive
|
||||
- Ensure consistent casing (camelCase, snake_case, etc.) per language conventions
|
||||
|
||||
**Pattern Consolidation:**
|
||||
- Extract repeated patterns into helper functions
|
||||
- Replace verbose constructs with idiomatic alternatives
|
||||
- Consolidate similar conditional blocks
|
||||
|
||||
### 3. What You Must NOT Do
|
||||
- Change the external behavior or API of the code
|
||||
- Add new features or functionality
|
||||
- Remove code that appears unused but may be used via reflection/dynamic calls
|
||||
- Make stylistic changes that contradict the project's established conventions
|
||||
- Optimize for performance unless it also improves readability
|
||||
|
||||
### 4. Quality Verification
|
||||
After each cleaning operation:
|
||||
- Verify all function signatures remain unchanged
|
||||
- Confirm all exports/public interfaces are preserved
|
||||
- Check that no referenced variables or functions were accidentally removed
|
||||
- Ensure the code would still pass existing tests
|
||||
|
||||
### 5. Output Standards
|
||||
|
||||
When presenting cleaned code:
|
||||
- Show the complete cleaned file, not just snippets
|
||||
- Provide a brief summary of changes made
|
||||
- Categorize changes (e.g., "Removed 3 unused imports", "Consolidated 2 duplicate functions")
|
||||
- Flag any areas where you chose not to make changes and explain why
|
||||
|
||||
### 6. Decision Framework
|
||||
|
||||
When uncertain about a change, ask yourself:
|
||||
1. Does this change preserve exact functionality? If no → don't do it
|
||||
2. Does this change improve readability? If no → reconsider
|
||||
3. Does this change follow the project's existing patterns? If no → adapt or skip
|
||||
4. Could this change break something not visible in the current context? If yes → flag it and ask
|
||||
|
||||
### 7. Communication Style
|
||||
- Be concise but thorough in explanations
|
||||
- Use bullet points for listing changes
|
||||
- Provide before/after comparisons for significant refactors
|
||||
- Ask clarifying questions if the scope of cleaning is unclear
|
||||
|
||||
You take pride in leaving code cleaner than you found it, treating every file as an opportunity to demonstrate the art of clean code. Your changes are surgical, purposeful, and always in service of maintainability.
|
||||
@@ -0,0 +1,91 @@
|
||||
---
|
||||
name: nixos-config-researcher
|
||||
description: Use this agent when you need to find documentation, configuration options, module syntax, or best practices for NixOS configuration. This includes researching Nix language features, Home Manager options, flake patterns, specific package configurations, or debugging NixOS module issues. Examples:\n\n- User: "How do I configure Hyprland in NixOS?"\n Assistant: "Let me use the nixos-config-researcher agent to find the proper configuration options for Hyprland in NixOS."\n <uses Task tool to launch nixos-config-researcher>\n\n- User: "What's the correct syntax for SOPS secrets in NixOS?"\n Assistant: "I'll research this using the nixos-config-researcher agent to find the official documentation."\n <uses Task tool to launch nixos-config-researcher>\n\n- User: "I'm getting an error with my NixOS module, it says 'infinite recursion encountered'"\n Assistant: "Let me use the nixos-config-researcher agent to find documentation on this error and common solutions."\n <uses Task tool to launch nixos-config-researcher>\n\n- User: "How do I set up Stylix theming?"\n Assistant: "I'll have the nixos-config-researcher agent look up the Stylix documentation and configuration options."\n <uses Task tool to launch nixos-config-researcher>
|
||||
model: sonnet
|
||||
color: blue
|
||||
---
|
||||
|
||||
You are an expert NixOS configuration researcher with deep knowledge of the Nix ecosystem, NixOS modules, Home Manager, and flake-based configurations. Your primary mission is to find accurate, up-to-date information about NixOS configuration by searching authoritative sources.
|
||||
|
||||
## Research Priority Order
|
||||
|
||||
Always search sources in this priority order:
|
||||
|
||||
1. **Official Documentation First**
|
||||
- NixOS Manual (nixos.org/manual/nixos)
|
||||
- NixOS Options Search (search.nixos.org/options)
|
||||
- NixOS Packages Search (search.nixos.org/packages)
|
||||
- Nix Reference Manual (nixos.org/manual/nix)
|
||||
- Home Manager Manual and Options (nix-community.github.io/home-manager)
|
||||
- Nixpkgs Manual (nixos.org/manual/nixpkgs)
|
||||
|
||||
2. **Project-Specific Documentation**
|
||||
- GitHub repositories of specific projects (READMEs, wikis)
|
||||
- Official project documentation sites
|
||||
- Flake documentation for community flakes
|
||||
|
||||
3. **Community Resources**
|
||||
- NixOS Wiki (nixos.wiki)
|
||||
- NixOS Discourse (discourse.nixos.org)
|
||||
- Nix community GitHub discussions
|
||||
|
||||
4. **Last Resort Sources**
|
||||
- Blog posts and tutorials (verify against official docs)
|
||||
- Stack Overflow answers
|
||||
- Reddit r/NixOS discussions
|
||||
|
||||
## Research Methodology
|
||||
|
||||
1. **Understand the Query**: Parse what specific aspect of NixOS configuration is being asked about - is it a module option, a package configuration, a flake pattern, or a general concept?
|
||||
|
||||
2. **Search Strategically**: Use specific search terms including:
|
||||
- "nixos" + the specific topic
|
||||
- "home-manager" if it's user-level configuration
|
||||
- Module paths like "services.x" or "programs.y"
|
||||
- Include "option" or "module" for configuration questions
|
||||
|
||||
3. **Verify Information**:
|
||||
- Cross-reference findings with official NixOS options search when possible
|
||||
- Check the Nix version relevance (some options change between versions)
|
||||
- Prefer declarative/flake-based solutions over imperative ones
|
||||
|
||||
4. **Contextualize for the User's Setup**: When relevant, consider:
|
||||
- Flake-based configurations (the modern approach)
|
||||
- Home Manager integration
|
||||
- System vs user-level configuration distinctions
|
||||
|
||||
## Output Format
|
||||
|
||||
When presenting research findings:
|
||||
|
||||
1. **Source Attribution**: Always cite where the information comes from
|
||||
2. **Code Examples**: Provide Nix code snippets when applicable
|
||||
3. **Option Paths**: Include full option paths (e.g., `services.openssh.enable`)
|
||||
4. **Confidence Level**: Indicate if information is from official docs vs community sources
|
||||
5. **Version Notes**: Mention if configuration syntax is version-specific
|
||||
|
||||
## Quality Standards
|
||||
|
||||
- Never fabricate NixOS options or module paths - verify they exist
|
||||
- Prefer showing the actual option type and default values when available
|
||||
- Include import statements or flake input requirements when relevant
|
||||
- Warn about deprecated options or patterns when encountered
|
||||
- If official documentation is insufficient, clearly state this and explain the alternative source used
|
||||
|
||||
## Example Response Structure
|
||||
|
||||
```
|
||||
**Source**: [Official/Community] - [specific URL or reference]
|
||||
|
||||
**Configuration**:
|
||||
```nix
|
||||
# Example code
|
||||
```
|
||||
|
||||
**Key Options**:
|
||||
- `option.path` (type): description
|
||||
|
||||
**Notes**: Any caveats, version requirements, or additional context
|
||||
```
|
||||
|
||||
You are thorough, accurate, and always prioritize official documentation. When you cannot find definitive answers, you clearly communicate the limitations of available information rather than guessing.
|
||||
@@ -0,0 +1,147 @@
|
||||
---
|
||||
name: security-paranoid-advisor
|
||||
description: Use this agent when you need a thorough security review of code, configurations, dependencies, or architectural decisions. This includes reviewing pull requests for security vulnerabilities, auditing existing codebases for potential exploits, analyzing authentication/authorization implementations, checking for data exposure risks, reviewing API endpoints for attack vectors, examining dependency chains for known vulnerabilities, or whenever security implications of any code change need to be assessed. This agent should be called proactively after writing code that handles user input, authentication, file operations, network requests, database queries, or any sensitive data processing.\n\nExamples:\n\n<example>\nContext: User just wrote a login authentication function\nuser: "Please implement a user login function that checks username and password"\nassistant: "Here is the login implementation:"\n<function implementation of login handler>\nassistant: "Now let me use the security-paranoid-advisor agent to review this authentication code for vulnerabilities"\n<commentary>\nSince authentication code was just written, use the security-paranoid-advisor agent to check for timing attacks, SQL injection, credential handling issues, and session management vulnerabilities.\n</commentary>\n</example>\n\n<example>\nContext: User is adding a file upload feature\nuser: "Add an endpoint that lets users upload profile pictures"\nassistant: "I'll implement the file upload endpoint"\n<function implementation of upload handler>\nassistant: "Let me invoke the security-paranoid-advisor agent to audit this file upload implementation for potential attack vectors"\n<commentary>\nFile uploads are high-risk features. Use the security-paranoid-advisor agent to check for path traversal, file type validation bypass, malicious file execution, and storage vulnerabilities.\n</commentary>\n</example>\n\n<example>\nContext: User asks for a security review of recent changes\nuser: "Can you check if there are any security issues in the code I just wrote?"\nassistant: "I'll use the security-paranoid-advisor agent to perform a comprehensive security audit of the recent code changes"\n<commentary>\nDirect security review request - use the security-paranoid-advisor agent to perform deep analysis of all recent modifications.\n</commentary>\n</example>
|
||||
model: sonnet
|
||||
color: red
|
||||
---
|
||||
|
||||
You are an elite security advisor with decades of experience in offensive security, penetration testing, and secure code review. You have discovered zero-day vulnerabilities, led red team operations, and reviewed code for financial institutions and government agencies. Your paranoia has saved countless systems from catastrophic breaches. You think like an attacker but protect like a guardian.
|
||||
|
||||
## Your Mandate
|
||||
|
||||
You exist to find what others miss. Every line of code is a potential attack surface. Every assumption is a vulnerability waiting to be exploited. Trust nothing. Verify everything. Your job is to be the adversary before the real adversaries arrive.
|
||||
|
||||
## Core Security Domains You Must Scrutinize
|
||||
|
||||
### Input Validation & Injection Attacks
|
||||
- SQL injection (including second-order, blind, and time-based variants)
|
||||
- Command injection and OS command execution
|
||||
- LDAP, XML, XPath, and NoSQL injection
|
||||
- Template injection (SSTI)
|
||||
- Header injection and CRLF attacks
|
||||
- Path traversal and local/remote file inclusion
|
||||
- Prototype pollution in JavaScript
|
||||
- Deserialization vulnerabilities
|
||||
|
||||
### Authentication & Session Management
|
||||
- Credential storage (plaintext, weak hashing, missing salt)
|
||||
- Timing attacks on authentication
|
||||
- Session fixation and hijacking
|
||||
- JWT vulnerabilities (algorithm confusion, weak secrets, missing expiration)
|
||||
- OAuth/OIDC misconfigurations
|
||||
- Multi-factor authentication bypasses
|
||||
- Password reset flow vulnerabilities
|
||||
- Brute force and credential stuffing exposure
|
||||
|
||||
### Authorization & Access Control
|
||||
- Broken object-level authorization (IDOR)
|
||||
- Function-level access control failures
|
||||
- Privilege escalation paths
|
||||
- Missing authorization checks on sensitive operations
|
||||
- Role-based access control gaps
|
||||
- Horizontal and vertical privilege escalation
|
||||
|
||||
### Data Exposure & Privacy
|
||||
- Sensitive data in logs, errors, or responses
|
||||
- PII exposure and GDPR/privacy violations
|
||||
- Secrets in code, configs, or version control
|
||||
- Information disclosure through verbose errors
|
||||
- Cache poisoning and sensitive data caching
|
||||
- Backup file exposure
|
||||
|
||||
### Cryptographic Failures
|
||||
- Weak or deprecated algorithms (MD5, SHA1 for security, DES, RC4)
|
||||
- Hardcoded keys and secrets
|
||||
- Improper random number generation
|
||||
- Missing or improper certificate validation
|
||||
- Encryption without authentication (use AEAD)
|
||||
- Key management vulnerabilities
|
||||
|
||||
### API & Network Security
|
||||
- Rate limiting and denial of service vectors
|
||||
- CORS misconfigurations
|
||||
- SSRF (Server-Side Request Forgery)
|
||||
- Mass assignment vulnerabilities
|
||||
- GraphQL-specific attacks (introspection, batching, depth attacks)
|
||||
- WebSocket security issues
|
||||
- HTTP security headers (CSP, HSTS, X-Frame-Options)
|
||||
|
||||
### Dependency & Supply Chain
|
||||
- Known vulnerable dependencies (CVEs)
|
||||
- Typosquatting risks
|
||||
- Dependency confusion attacks
|
||||
- Outdated packages with security patches
|
||||
- Malicious package indicators
|
||||
|
||||
### Infrastructure & Configuration
|
||||
- Debug mode in production
|
||||
- Default credentials
|
||||
- Exposed admin interfaces
|
||||
- Insecure file permissions
|
||||
- Docker/container security misconfigurations
|
||||
- Cloud IAM and resource policy issues
|
||||
- Environment variable exposure
|
||||
|
||||
## Your Review Methodology
|
||||
|
||||
1. **Map the Attack Surface**: Identify all entry points, data flows, trust boundaries, and external integrations.
|
||||
|
||||
2. **Assume Breach Mentality**: Consider what damage could be done if each component were compromised.
|
||||
|
||||
3. **Trace Data Flows**: Follow user-controlled data from input to storage to output. Every transformation is a potential vulnerability.
|
||||
|
||||
4. **Check the Obvious AND the Obscure**: Attackers exploit both simple oversights and complex logic flaws.
|
||||
|
||||
5. **Consider Chained Attacks**: Low-severity issues can combine into critical exploits.
|
||||
|
||||
6. **Review Error Handling**: Errors often leak sensitive information or create unexpected states.
|
||||
|
||||
7. **Examine Race Conditions**: Look for TOCTOU (time-of-check to time-of-use) vulnerabilities.
|
||||
|
||||
8. **Verify Negative Cases**: Ensure the code handles malicious input, not just valid input.
|
||||
|
||||
## Output Format
|
||||
|
||||
For each finding, provide:
|
||||
|
||||
### [SEVERITY: CRITICAL|HIGH|MEDIUM|LOW|INFO] - Brief Title
|
||||
|
||||
**Location**: File path and line numbers
|
||||
|
||||
**Vulnerability Type**: CWE category if applicable
|
||||
|
||||
**Description**: What the vulnerability is and why it's dangerous
|
||||
|
||||
**Attack Scenario**: Concrete example of how an attacker would exploit this
|
||||
|
||||
**Evidence**: The specific code or configuration that's vulnerable
|
||||
|
||||
**Remediation**: Exact steps to fix, with code examples when helpful
|
||||
|
||||
**References**: Relevant security resources or documentation
|
||||
|
||||
---
|
||||
|
||||
## Behavioral Guidelines
|
||||
|
||||
- **Be Thorough**: Check every file, every function, every configuration. The vulnerability you skip is the one that gets exploited.
|
||||
|
||||
- **Be Specific**: Vague warnings are useless. Point to exact lines, provide exact attack payloads, give exact fixes.
|
||||
|
||||
- **Be Paranoid**: If something could be abused, assume it will be. Defense in depth is not optional.
|
||||
|
||||
- **Prioritize Ruthlessly**: Critical vulnerabilities that are easily exploitable come first. But report everything.
|
||||
|
||||
- **Explain the Impact**: Help developers understand why this matters. "An attacker could..." is more compelling than "This is insecure."
|
||||
|
||||
- **Consider the Context**: A vulnerability in an internal tool differs from one in a public-facing API, but both matter.
|
||||
|
||||
- **Don't Trust Mitigations Elsewhere**: If input validation exists at the frontend, verify it exists at the backend too.
|
||||
|
||||
- **Check Comments and TODOs**: Developers often leave security debt documented in comments.
|
||||
|
||||
- **Examine Test Files**: They sometimes contain hardcoded credentials or reveal security assumptions.
|
||||
|
||||
- **Review Git History When Relevant**: Security fixes sometimes get reverted or contain remnants of vulnerabilities.
|
||||
|
||||
You are the last line of defense before code reaches production. Miss nothing. Question everything. Protect this repository as if your reputation depends on it—because it does.
|
||||
@@ -0,0 +1,7 @@
|
||||
keys:
|
||||
- &user_kenji age1dhmt5tdyxd9zam542zkr9hq4tku7lzmf6j057sjtepk80deky5fqemczs5
|
||||
creation_rules:
|
||||
- path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
|
||||
key_groups:
|
||||
- age:
|
||||
- *user_kenji
|
||||
@@ -0,0 +1,120 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Build Commands
|
||||
|
||||
```bash
|
||||
# Rebuild and switch to new configuration (desktop x86_64)
|
||||
sudo nixos-rebuild switch --flake ~/.config/nixos/#hakase
|
||||
|
||||
# Rebuild MacBook configuration (aarch64)
|
||||
sudo nixos-rebuild switch --flake ~/.config/nixos/#macbook
|
||||
|
||||
# Dry-run build to check for errors without applying
|
||||
sudo nixos-rebuild build --flake ~/.config/nixos/#hakase
|
||||
|
||||
# Manage SOPS secrets
|
||||
nix-shell -p sops --run "sops secrets/secrets.yaml"
|
||||
nix-shell -p sops --run "sops updatekeys secrets/secrets.yaml"
|
||||
```
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
This is a modular, flake-based NixOS configuration supporting two hosts: `hakase` (x86_64 desktop) and `macbook` (aarch64 Apple Silicon).
|
||||
|
||||
### Key Entry Points
|
||||
|
||||
- `flake.nix` - Declares inputs and creates both NixOS configurations (hakase, macbook)
|
||||
- `config.nix` - Central configuration values separated by host (hakase, macbook keys)
|
||||
- `hosts/{hakase,macbook}/configuration.nix` - Host-level entry points importing system modules
|
||||
- `home/hakase.nix` - Home Manager entry point for user environment (referenced from flake)
|
||||
|
||||
### Module Organization
|
||||
|
||||
**Three-tier system:**
|
||||
1. **System modules** (`modules/nixos/`) - NixOS-level settings (boot, kernel, services, hardware)
|
||||
2. **Home Manager modules** (`modules/home/`) - User-level environment and applications
|
||||
3. **Application configs** (`apps/`) - Per-application configuration directories with `default.nix` files
|
||||
|
||||
Examples:
|
||||
- `apps/hyprland/default.nix` + `apps/hyprland/hypr/*.nix` - Hyprland compositor config
|
||||
- `apps/firefox/default.nix` - Browser with bookmarks and theming
|
||||
- `apps/ghostty/default.nix` - Terminal emulator
|
||||
- `apps/neovim/default.nix` - Editor (via nixovim external flake)
|
||||
|
||||
### Configuration Flow
|
||||
|
||||
```
|
||||
flake.nix (outputs)
|
||||
├─ hakase (x86_64-linux)
|
||||
│ ├─ hosts/hakase/configuration.nix
|
||||
│ │ └─ modules/nixos/default.nix (imports system modules)
|
||||
│ └─ home-manager
|
||||
│ └─ home/hakase.nix
|
||||
│ └─ modules/home/* (imports Home Manager modules)
|
||||
│ └─ apps/* (application configurations)
|
||||
│
|
||||
└─ macbook (aarch64-linux)
|
||||
├─ hosts/macbook/configuration.nix
|
||||
│ └─ modules/nixos/default.nix
|
||||
└─ Similar home-manager structure
|
||||
|
||||
config.nix provides myConfig via specialArgs to both configurations
|
||||
```
|
||||
|
||||
### Configuration Structure (config.nix)
|
||||
|
||||
The `config.nix` file defines host-specific configuration under `hakase` and `macbook` keys. Common values include:
|
||||
|
||||
```nix
|
||||
myConfig = {
|
||||
nixos = { username, hostname, timezone }
|
||||
git = { username, email, defaultBranch }
|
||||
theme = { mode } # "dark" or "light"
|
||||
terminal = { default, font, aliases }
|
||||
font = { monospace, monospaceScript, sans }
|
||||
hyprland = { monitors, wallpaper, kb_options }
|
||||
firefox = { bookmarks, newtabpage }
|
||||
# ... more app-specific configs
|
||||
}
|
||||
```
|
||||
|
||||
To add a host-specific override, define it in the host's `myConfig` section in `config.nix`. The flake passes `allConfig.{hostname}` as specialArgs, so modules access the correct host configuration.
|
||||
|
||||
### Module Pattern
|
||||
|
||||
Modules receive standard NixOS parameters plus custom ones:
|
||||
```nix
|
||||
{ pkgs, config, lib, myConfig, inputs, system, ... }:
|
||||
```
|
||||
|
||||
**Key patterns:**
|
||||
- Access host config: `myConfig.nixos.username`, `myConfig.terminal.default`
|
||||
- Use host-specific packages: `pkgs.unstable` (from nixpkgs), `inputs.neovim` (from flake inputs)
|
||||
- Reference other modules via `config` (e.g., `config.home.homeDirectory`)
|
||||
- Conditional logic: Check `system` or `myConfig` values
|
||||
|
||||
### Secrets Management
|
||||
|
||||
SOPS-encrypted secrets stored in `secrets/secrets.yaml`. Age key at `~/.config/sops/age/keys.txt`.
|
||||
|
||||
In modules, reference secrets via:
|
||||
```nix
|
||||
config.sops.secrets.secret_name.path
|
||||
```
|
||||
|
||||
## Key Technologies
|
||||
|
||||
- **Hyprland** with UWSM (systemd user session management)
|
||||
- **Matugen** for automatic system-wide theming from wallpaper colors
|
||||
- **Home Manager** for user environment and program configuration
|
||||
- **nixovim** external flake for Neovim configuration (treesitter disabled due to read-only NixOS constraints)
|
||||
- **SOPS-Nix** for secrets encryption
|
||||
- **CachyOS kernel** on hakase (x86_64), **Asahi Linux** on macbook (aarch64)
|
||||
|
||||
## Git Commit Convention
|
||||
|
||||
Use conventional commits with scope: `feat(scope):`, `fix(scope):`, `refactor:`, `add:`, `remove:`, `cleanup:`
|
||||
|
||||
Common scopes: `nixos`, `home`, `apps`, `config`, `modules`, `hyprland`, `firefox`, etc.
|
||||
@@ -0,0 +1,65 @@
|
||||
# HakaseOS - NixOS Configuration
|
||||
|
||||
This is a modular, flake-based NixOS configuration for a single host (`hakase`). It features a custom Hyprland desktop environment, automated theming via Matugen, and strict separation of concerns using a custom `myConfig` object.
|
||||
|
||||
## Project Structure
|
||||
|
||||
* **`flake.nix`**: The entry point. Defines inputs (Hyprland, Chaotic, Home Manager, etc.) and creates the system configuration.
|
||||
* **`config.nix`**: Central source of truth. Defines global variables (user details, monitor config, theme settings) exposed as `myConfig`.
|
||||
* **`hosts/hakase/`**: Host-specific configuration.
|
||||
* `configuration.nix`: Main system entry point.
|
||||
* **`modules/`**: Reusable modules.
|
||||
* `nixos/`: System-level modules (boot, hardware, services).
|
||||
* `home/`: Home-manager modules (UI, apps, user services).
|
||||
* **`apps/`**: Application-specific configurations. Each app has its own directory (e.g., `hyprland`, `firefox`, `ghostty`) with a `default.nix`.
|
||||
* **`assets/`**: Static assets like wallpapers (`firewatch.png`).
|
||||
* **`secrets/`**: Encrypted secrets managed by SOPS.
|
||||
|
||||
## Architecture & Conventions
|
||||
|
||||
### 1. The `myConfig` Object
|
||||
Global configuration is not hardcoded in modules. Instead, it is defined in `config.nix` and passed to all modules via `specialArgs`.
|
||||
**Usage Pattern:**
|
||||
```nix
|
||||
# In any module
|
||||
{ pkgs, config, myConfig, ... }:
|
||||
{
|
||||
# Access values
|
||||
home.username = myConfig.nixos.username;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Module Hierarchy
|
||||
* **System**: `flake.nix` -> `hosts/hakase/configuration.nix` -> `modules/nixos/default.nix` -> `modules/nixos/*.nix`
|
||||
* **User**: `modules/nixos/user.nix` (or similar) -> `home-manager` -> `home/hakase.nix` -> `modules/home/*.nix` -> `apps/*/default.nix`
|
||||
|
||||
### 3. Application Configuration
|
||||
Do not dump config into one large file. Create a dedicated folder in `apps/<app_name>/` with a `default.nix`.
|
||||
* Example: `apps/ghostty/default.nix`
|
||||
|
||||
## Key Commands
|
||||
|
||||
### System Management
|
||||
* **Rebuild & Switch**:
|
||||
```bash
|
||||
sudo nixos-rebuild switch --flake ~/.config/nixos/#hakase
|
||||
# or alias:
|
||||
update
|
||||
```
|
||||
|
||||
### Secrets (SOPS)
|
||||
* **Edit Secrets**:
|
||||
```bash
|
||||
nix-shell -p sops --run "sops secrets/secrets.yaml"
|
||||
```
|
||||
* **Update Keys**:
|
||||
```bash
|
||||
nix-shell -p sops --run "sops updatekeys secrets/secrets.yaml"
|
||||
```
|
||||
|
||||
## Development Guidelines
|
||||
|
||||
* **Matugen**: used for theming. Templates are located in `apps/matugen/templates/`.
|
||||
* **Hyprland**: Config is split into `apps/hyprland/hypr/*.nix`.
|
||||
* **Formatting**: Follow existing indentation (2 spaces usually).
|
||||
* **Commits**: Use Conventional Commits (e.g., `feat(hyprland): add new bind`).
|
||||
@@ -1,58 +1,101 @@
|
||||
# Sakamoto NixOS
|
||||
# HakaseOS
|
||||
|
||||
Sakamoto NixOS is built with various profiles intended for reproducibility.
|
||||
A modular, flake-based NixOS configuration for my personal devices (`hakase` desktop and `macbook`). Heavily inspired by [OmarchyOS](https://omarchy.org/).
|
||||
|
||||
## Available Hosts
|
||||
## Features
|
||||
|
||||
- MacBook M series
|
||||
- Linux
|
||||
- **Hyprland** compositor with UWSM (systemd session management)
|
||||
- **Multi-Architecture Support**: Runs on x86_64 (Desktop) and aarch64 (Apple Silicon M1/M2)
|
||||
- **Matugen** for automatic system-wide theming from wallpaper colors
|
||||
- **Hardened Firefox** with custom bookmarks and new tab page
|
||||
- **Vim keybindings** throughout the system
|
||||
- **SOPS** for encrypted secrets management
|
||||
- **CachyOS kernel** (Desktop) and **Asahi Linux** (MacBook) support
|
||||
|
||||
## Installation
|
||||
## 🚧 TODO
|
||||
- LUKS designed
|
||||
|
||||
1. Install [Nix](https://nixos.org/download/).
|
||||
## Screenshots
|
||||
|
||||
2. Ensure Nix is installed properly by running the following (this also gives you `nano` for editing later):
|
||||

|
||||
|
||||
```sh
|
||||
nix-shell -p nano
|
||||
```
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
3. Clone the git repository:
|
||||
## Structure
|
||||
|
||||
```sh
|
||||
git clone https://git.sakamoto.dev/kenji/nixos.git ~/.config/nixos && cd ~/.config/nixos/
|
||||
```
|
||||
```
|
||||
.
|
||||
├── flake.nix # Entry point defining hosts (hakase, macbook)
|
||||
├── config.nix # Central configuration values per host
|
||||
├── hosts/
|
||||
│ ├── hakase/ # Desktop configuration (x86_64)
|
||||
│ └── macbook/ # Laptop configuration (aarch64, Apple Silicon)
|
||||
├── modules/
|
||||
│ ├── nixos/ # System-level modules (boot, kernel, services)
|
||||
│ └── home/ # Home Manager modules
|
||||
├── home/ # Host-specific Home Manager entry points
|
||||
├── apps/ # Per-application configurations
|
||||
│ ├── hyprland/ # Hyprland window manager
|
||||
│ ├── waybar/ # Status bar
|
||||
│ ├── firefox/ # Browser configuration
|
||||
│ ├── ghostty/ # Terminal emulator
|
||||
│ ├── neovim/ # Editor (via nixovim flake)
|
||||
│ ├── vicinae/ # Application launcher
|
||||
│ └── ... # And many more
|
||||
├── secrets/ # SOPS encrypted secrets
|
||||
└── assets/ # Wallpapers and other assets
|
||||
```
|
||||
|
||||
4. Copy `info.default.nix` and rename it to `info.local.nix`:
|
||||
## Usage
|
||||
|
||||
```sh
|
||||
cp ~/.config/nixos/info.default.nix ~/.config/nixos/info.local.nix
|
||||
```
|
||||
### Rebuild System
|
||||
|
||||
🚨 **CRITICAL STEP:** Edit `info.local.nix`:
|
||||
**Desktop (Hakase):**
|
||||
```bash
|
||||
sudo nixos-rebuild switch --flake ~/.config/nixos/#hakase
|
||||
```
|
||||
|
||||
```sh
|
||||
nano ~/.config/nixos/info.local.nix
|
||||
```
|
||||
**MacBook (Asahi):**
|
||||
```bash
|
||||
sudo nixos-rebuild switch --flake ~/.config/nixos/#macbook
|
||||
```
|
||||
|
||||
Modify it to fit your system — especially your **username**.
|
||||
If you accidentally leave the default `biscuit`, that user will be created.
|
||||
**Login password for `biscuit` is `<PLACEHOLDER>`.**
|
||||
### Manage Secrets
|
||||
|
||||
5. Execute the following command based on your host:
|
||||
```bash
|
||||
# Edit secrets
|
||||
nix-shell -p sops --run "sops secrets/secrets.yaml"
|
||||
|
||||
- **MacBook M series:**
|
||||
# Update keys
|
||||
nix-shell -p sops --run "sops updatekeys secrets/secrets.yaml"
|
||||
```
|
||||
|
||||
```sh
|
||||
sudo nix run nix-darwin --extra-experimental-features "nix-command flakes" -- switch --flake ~/.config/nixos#macos
|
||||
```
|
||||
## Configuration
|
||||
|
||||
- **Linux:**
|
||||
Central configuration values are defined in `config.nix`, separated by host:
|
||||
|
||||
```sh
|
||||
sudo nixos-rebuild --flake ~/.config/nixos#desktop --impure
|
||||
sudo nix run home-manager -- init --switch
|
||||
home-manager switch --flake ~/.config/nixos#desktop --impure
|
||||
nix-channel --add https://nixos.org/channels/nixos-unstable nixos nix-channel --update
|
||||
reboot
|
||||
```
|
||||
- `hakase` / `macbook` keys define host-specific overrides
|
||||
- `myConfig.nixos` - System settings (username, hostname, timezone)
|
||||
- `myConfig.hyprland` - Monitor configuration (Hz, Resolution) and wallpaper
|
||||
|
||||
## Flake Inputs
|
||||
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| nixpkgs | NixOS unstable |
|
||||
| home-manager | User environment management |
|
||||
| hyprland | Wayland compositor |
|
||||
| chaotic | CachyOS kernel and packages (x86 only) |
|
||||
| apple-silicon | Asahi Linux support for NixOS (aarch64 only) |
|
||||
| sops-nix | Secrets management |
|
||||
| nixovim | Neovim configuration |
|
||||
| matugen | System-wide theming |
|
||||
| vicinae | Application launcher |
|
||||
| textfox | Firefox CSS theme |
|
||||
|
||||
## License
|
||||
|
||||
Personal configuration - use at your own discretion.
|
||||
@@ -0,0 +1,12 @@
|
||||
{pkgs, ...}: {
|
||||
home.packages = with pkgs; [anki-bin];
|
||||
|
||||
xdg.mimeApps = {
|
||||
enable = true;
|
||||
defaultApplications = {
|
||||
"application/x-apkg" = "anki.desktop";
|
||||
"application/x-anki-deck" = "anki.desktop";
|
||||
"application/x-anki-collection" = "anki.desktop";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{pkgs, ...}: {
|
||||
programs.bottom = {
|
||||
enable = true;
|
||||
settings = {
|
||||
flags = {
|
||||
rate = 1000;
|
||||
hide_table_gap = true;
|
||||
hide_time = true;
|
||||
left_legend = true;
|
||||
network_use_bytes = true;
|
||||
temperature_type = "c";
|
||||
mem_as_value = true;
|
||||
current_usage = true;
|
||||
};
|
||||
row = [
|
||||
{
|
||||
ratio = 4;
|
||||
child = [
|
||||
{ type = "cpu"; }
|
||||
];
|
||||
}
|
||||
{
|
||||
ratio = 3;
|
||||
child = [
|
||||
{ type = "mem"; }
|
||||
{ type = "net"; }
|
||||
];
|
||||
}
|
||||
{
|
||||
ratio = 3;
|
||||
child = [
|
||||
{ type = "temp"; }
|
||||
{ type = "disk"; }
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
myConfig,
|
||||
...
|
||||
}: {
|
||||
# This enables the btop configuration file generation in your home directory.
|
||||
# The btop package itself is now installed system-wide via modules/nixos/btop.nix
|
||||
programs.btop = {
|
||||
enable = true;
|
||||
settings = {
|
||||
vim_keys = true;
|
||||
color_theme = "TTY";
|
||||
theme_background = false;
|
||||
presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty cpu:0:default,mem:0:default,net:0:default,gpu0:0:default";
|
||||
};
|
||||
};
|
||||
|
||||
# This updates your Hyprland settings to use the btop-power wrapper.
|
||||
wayland.windowManager.hyprland.settings = lib.mkMerge [
|
||||
{
|
||||
bindd = [
|
||||
"CTRL SHIFT, Escape, Open Btop Minimal, exec, uwsm app -- xdg-terminal-exec -e btop-power -p 2"
|
||||
];
|
||||
}
|
||||
(lib.mkIf (myConfig.btop.autostart) {
|
||||
exec-once = [
|
||||
"uwsm app -- xdg-terminal-exec -e btop-power -p 2"
|
||||
];
|
||||
windowrulev2 = [
|
||||
"monitor ${myConfig.btop.monitor}, title:^(btop)$"
|
||||
];
|
||||
})
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{pkgs, ...}: {
|
||||
home.packages = with pkgs; [
|
||||
cava
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{pkgs, ...}: {
|
||||
home.packages = with pkgs; [
|
||||
claude-code
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{pkgs, ...}: {
|
||||
home.packages = with pkgs; [delfin];
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
⣇⣿⠘⣿⣿⣿⡿⡿⣟⣟⢟⢟⢝⠵⡝⣿⡿⢂⣼⣿⣷⣌⠩⡫⡻⣝⠹⢿⣿⣷
|
||||
⡆⣿⣆⠱⣝⡵⣝⢅⠙⣿⢕⢕⢕⢕⢝⣥⢒⠅⣿⣿⣿⡿⣳⣌⠪⡪⣡⢑⢝⣇
|
||||
⡆⣿⣿⣦⠹⣳⣳⣕⢅⠈⢗⢕⢕⢕⢕⢕⢈⢆⠟⠋⠉⠁⠉⠉⠁⠈⠼⢐⢕⢽
|
||||
⡗⢰⣶⣶⣦⣝⢝⢕⢕⠅⡆⢕⢕⢕⢕⢕⣴⠏⣠⡶⠛⡉⡉⡛⢶⣦⡀⠐⣕⢕
|
||||
⡝⡄⢻⢟⣿⣿⣷⣕⣕⣅⣿⣔⣕⣵⣵⣿⣿⢠⣿⢠⣮⡈⣌⠨⠅⠹⣷⡀⢱⢕
|
||||
⡝⡵⠟⠈⢀⣀⣀⡀⠉⢿⣿⣿⣿⣿⣿⣿⣿⣼⣿⢈⡋⠴⢿⡟⣡⡇⣿⡇⡀⢕
|
||||
⡝⠁⣠⣾⠟⡉⡉⡉⠻⣦⣻⣿⣿⣿⣿⣿⣿⣿⣿⣧⠸⣿⣦⣥⣿⡇⡿⣰⢗⢄
|
||||
⠁⢰⣿⡏⣴⣌⠈⣌⠡⠈⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣬⣉⣉⣁⣄⢖⢕⢕⢕
|
||||
⡀⢻⣿⡇⢙⠁⠴⢿⡟⣡⡆⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣵⣵⣿
|
||||
⡻⣄⣻⣿⣌⠘⢿⣷⣥⣿⠇⣿⣿⣿⣿⣿⣿⠛⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
||||
⣷⢄⠻⣿⣟⠿⠦⠍⠉⣡⣾⣿⣿⣿⣿⣿⣿⢸⣿⣦⠙⣿⣿⣿⣿⣿⣿⣿⣿⠟
|
||||
⡕⡑⣑⣈⣻⢗⢟⢞⢝⣻⣿⣿⣿⣿⣿⣿⣿⠸⣿⠿⠃⣿⣿⣿⣿⣿⣿⡿⠁⣠
|
||||
⡝⡵⡈⢟⢕⢕⢕⢕⣵⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣶⣿⣿⣿⣿⣿⠿⠋⣀⣈⠙
|
||||
⡝⡵⡕⡀⠑⠳⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠛⢉⡠⡲⡫⡪⡪⡣
|
||||
@@ -0,0 +1,113 @@
|
||||
{pkgs, ...}: {
|
||||
programs.fastfetch = {
|
||||
enable = true;
|
||||
settings = {
|
||||
"$schema" = "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json";
|
||||
logo = {
|
||||
source = "~/.config/fastfetch/animo.txt";
|
||||
padding = {
|
||||
top = 1;
|
||||
};
|
||||
};
|
||||
display = {
|
||||
separator = " : ";
|
||||
};
|
||||
modules = [
|
||||
{
|
||||
type = "command";
|
||||
key = " ";
|
||||
keyColor = "blue";
|
||||
text = "splash=$(hakase-hyprlock-text-generator);echo $splash";
|
||||
}
|
||||
{
|
||||
type = "custom";
|
||||
format = "╭──────────────────────────────────────────╮";
|
||||
}
|
||||
{
|
||||
type = "os";
|
||||
key = " OS";
|
||||
format = "{2}";
|
||||
keyColor = "red";
|
||||
}
|
||||
{
|
||||
type = "kernel";
|
||||
key = " Kernel";
|
||||
format = "{2}";
|
||||
keyColor = "red";
|
||||
}
|
||||
{
|
||||
type = "packages";
|
||||
key = " Pkgs";
|
||||
keyColor = "green";
|
||||
}
|
||||
{
|
||||
type = "terminal";
|
||||
key = " Terminal";
|
||||
keyColor = "yellow";
|
||||
}
|
||||
{
|
||||
type = "wm";
|
||||
key = " WM";
|
||||
format = "{2}";
|
||||
keyColor = "yellow";
|
||||
}
|
||||
{
|
||||
type = "custom";
|
||||
format = "╰──────────────────────────────────────────╯";
|
||||
}
|
||||
"break"
|
||||
{
|
||||
type = "title";
|
||||
key = " ";
|
||||
format = "{6} {7} {8}";
|
||||
}
|
||||
{
|
||||
type = "custom";
|
||||
format = "╭──────────────────────────────────────────╮";
|
||||
}
|
||||
{
|
||||
type = "cpu";
|
||||
format = "{1} @ {7}";
|
||||
key = " CPU";
|
||||
keyColor = "blue";
|
||||
}
|
||||
{
|
||||
type = "gpu";
|
||||
format = "{1} {2}";
|
||||
key = " GPU";
|
||||
keyColor = "blue";
|
||||
hideType = "integrated";
|
||||
}
|
||||
{
|
||||
type = "memory";
|
||||
key = " Memory";
|
||||
keyColor = "magenta";
|
||||
}
|
||||
{
|
||||
type = "disk";
|
||||
key = " OS Age";
|
||||
folders = "/";
|
||||
keyColor = "red";
|
||||
format = "{days} days";
|
||||
}
|
||||
{
|
||||
type = "uptime";
|
||||
key = " Uptime";
|
||||
keyColor = "red";
|
||||
}
|
||||
{
|
||||
type = "custom";
|
||||
format = "╰──────────────────────────────────────────╯";
|
||||
}
|
||||
{
|
||||
type = "colors";
|
||||
paddingLeft = 2;
|
||||
symbol = "circle";
|
||||
}
|
||||
"break"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
home.file.".config/fastfetch/animo.txt".source = ./animo.txt;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{pkgs, ...}: {
|
||||
wayland.windowManager.hyprland.settings.exec-once = [
|
||||
"fcitx5 -d --replace"
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
{
|
||||
pkgs,
|
||||
myConfig,
|
||||
inputs,
|
||||
...
|
||||
}: {
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
exec-once = [
|
||||
"uwsm app -- pywalfox start"
|
||||
];
|
||||
|
||||
bindd = [
|
||||
"SUPER, W, Open Browser, exec, uwsm app -- firefox"
|
||||
"SUPER, Y, Toggle YouTube, togglespecialworkspace, youtube"
|
||||
"SUPER SHIFT, Y, Move to YouTube Special Workspace, movetoworkspace, special:youtube"
|
||||
"SUPER, I, Toggle Jellyfin, togglespecialworkspace, jellyfin"
|
||||
"SUPER SHIFT, I, Move to Jellyfin Special Workspace, movetoworkspace, special:jellyfin"
|
||||
];
|
||||
|
||||
workspace = [
|
||||
"special:youtube, on-created-empty:uwsm app -- firefox -P web-app --name youtube https://youtube.com"
|
||||
"special:jellyfin, on-created-empty:uwsm app -- firefox -P web-app --name jellyfin https://watch.sakamoto.dev"
|
||||
];
|
||||
|
||||
windowrulev2 = [
|
||||
"opacity 0.99 0.99, class:(?i)(firefox|youtube|jellyfin)"
|
||||
"workspace special:youtube, class:^(youtube)$"
|
||||
"workspace special:jellyfin, class:^(jellyfin)$"
|
||||
];
|
||||
};
|
||||
imports = [
|
||||
inputs.textfox.homeManagerModules.default
|
||||
./textfox.nix
|
||||
];
|
||||
home.packages = with pkgs; [
|
||||
pywalfox-native
|
||||
tridactyl-native
|
||||
];
|
||||
|
||||
home.file.".config/tridactyl/tridactylrc".text = ''
|
||||
set focusbypass true
|
||||
set smoothscroll true
|
||||
bind J tabnext
|
||||
bind K tabprev
|
||||
unbind <C-e>
|
||||
|
||||
" Force Tridactyl to yield new tab control to Firefox/Extensions
|
||||
set newtab about:newtab
|
||||
'';
|
||||
|
||||
programs.firefox = {
|
||||
enable = true;
|
||||
languagePacks = ["en-US"];
|
||||
nativeMessagingHosts = [
|
||||
pkgs.pywalfox-native
|
||||
pkgs.tridactyl-native
|
||||
];
|
||||
|
||||
profiles = {
|
||||
youtube = import ./profiles/web-app.nix {
|
||||
inherit pkgs myConfig;
|
||||
id = 1;
|
||||
name = "YouTube";
|
||||
url = "https://youtube.com";
|
||||
};
|
||||
jellyfin = import ./profiles/web-app.nix {
|
||||
inherit pkgs myConfig;
|
||||
id = 2;
|
||||
name = "Jellyfin";
|
||||
url = "https://watch.sakamoto.dev";
|
||||
};
|
||||
web-app = import ./profiles/web-app.nix {
|
||||
inherit pkgs myConfig;
|
||||
id = 3;
|
||||
name = "web-app";
|
||||
url = "about:blank";
|
||||
};
|
||||
hakase = {
|
||||
search.force = true;
|
||||
isDefault = true;
|
||||
search.default = "ddg";
|
||||
extensions.packages = with pkgs.nur.repos.rycee.firefox-addons; [
|
||||
pywalfox
|
||||
ublock-origin
|
||||
bitwarden
|
||||
tridactyl
|
||||
new-tab-override
|
||||
];
|
||||
|
||||
bookmarks = {
|
||||
force = true;
|
||||
settings = [
|
||||
{
|
||||
name = "Toolbar Bookmarks";
|
||||
toolbar = true;
|
||||
bookmarks = myConfig.firefox.bookmarks;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
settings = {
|
||||
# --- Privacy & Hardening ---
|
||||
"browser.contentblocking.category" = "strict";
|
||||
"geo.enabled" = false;
|
||||
"media.peerconnection.enabled" = false; # Prevents WebRTC IP leaks
|
||||
"network.dns.disablePrefetch" = true;
|
||||
"network.prefetch-next" = false;
|
||||
"privacy.resistFingerprinting" = true; # Note: Spoofs timezone and caps FPS to 60
|
||||
"privacy.trackingprotection.enabled" = true;
|
||||
|
||||
# --- NixOS / Hyprland Integration ---
|
||||
"widget.use-xdg-desktop-portal.file-picker" = 1; # Use native file picker
|
||||
|
||||
# --- UI & Behavior ---
|
||||
"accessibility.typeaheadfind" = false;
|
||||
"browser.compactmode.show" = true;
|
||||
"browser.formfill.enable" = false;
|
||||
"browser.newtabpage.activity-stream.feeds.section.topstories" = false;
|
||||
"browser.newtabpage.activity-stream.feeds.snippets" = false;
|
||||
"browser.newtabpage.activity-stream.section.highlights.includeBookmarks" = false;
|
||||
"browser.newtabpage.activity-stream.section.highlights.includeDownloads" = false;
|
||||
"browser.newtabpage.activity-stream.section.highlights.includePocket" = false;
|
||||
"browser.newtabpage.activity-stream.section.highlights.includeVisited" = false;
|
||||
"browser.newtabpage.activity-stream.showSponsored" = false;
|
||||
"browser.newtabpage.activity-stream.showSponsoredTopSites" = false;
|
||||
"browser.newtabpage.activity-stream.system.showSponsored" = false;
|
||||
"browser.search.suggest.enabled" = false;
|
||||
"browser.search.suggest.enabled.private" = false;
|
||||
"browser.tabs.closeWindowWithLastTab" = false;
|
||||
"browser.topsites.contile.enabled" = false;
|
||||
"browser.urlbar.showSearchSuggestionsFirst" = false;
|
||||
"browser.urlbar.suggest.searches" = false;
|
||||
"extensions.pocket.enabled" = false;
|
||||
"extensions.screenshots.disabled" = true;
|
||||
|
||||
# --- Homepage & Navigation ---
|
||||
"browser.newtabpage.pinned" = myConfig.firefox.newtabpage;
|
||||
"browser.startup.homepage" = "https://dash.sakamoto.dev";
|
||||
|
||||
# --- DNS over HTTPS (Quad9) ---
|
||||
"network.trr.mode" = 2; # Use DoH with system fallback
|
||||
"network.trr.uri" = "https://dns.quad9.net/dns-query";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
policies = {
|
||||
DisableTelemetry = true;
|
||||
DisableFirefoxStudies = true;
|
||||
EnableTrackingProtection = {
|
||||
Value = true;
|
||||
Locked = false;
|
||||
Cryptomining = true;
|
||||
Fingerprinting = true;
|
||||
};
|
||||
DisablePocket = true;
|
||||
DisableFirefoxAccounts = true;
|
||||
DisableAccounts = true;
|
||||
DisableFirefoxScreenshots = true;
|
||||
OverrideFirstRunPage = "";
|
||||
OverridePostUpdatePage = "";
|
||||
DontCheckDefaultBrowser = true;
|
||||
DisplayBookmarksToolbar = "always";
|
||||
SearchBar = "unified";
|
||||
|
||||
# Power User Messaging
|
||||
UserMessaging = {
|
||||
ExtensionRecommendations = false;
|
||||
SkipOnboarding = true;
|
||||
FeatureRecommendations = false;
|
||||
UrlbarInterventions = false;
|
||||
WhatsNew = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
{
|
||||
pkgs,
|
||||
myConfig,
|
||||
id,
|
||||
name,
|
||||
url,
|
||||
...
|
||||
}: {
|
||||
inherit id name;
|
||||
# Note: This profile relies on the global tridactylrc logic in default.nix
|
||||
# to dynamically set 'newtab' via the TRIDACTYL_NEWTAB environment variable.
|
||||
search.force = true;
|
||||
search.default = "ddg";
|
||||
extensions.force = true;
|
||||
extensions.packages = with pkgs.nur.repos.rycee.firefox-addons; [
|
||||
ublock-origin
|
||||
bitwarden
|
||||
tridactyl
|
||||
new-tab-override
|
||||
pywalfox
|
||||
];
|
||||
|
||||
settings = {
|
||||
# --- New Tab Override ---
|
||||
"extensions.newtaboverride@agenedia.com.url" = url;
|
||||
"extensions.newtaboverride@agenedia.com.type" = 1; # URL mode
|
||||
|
||||
# --- Privacy & Hardening ---
|
||||
"browser.contentblocking.category" = "strict";
|
||||
"privacy.trackingprotection.enabled" = true;
|
||||
"privacy.resistFingerprinting" = true; # Note: Spoofs timezone and caps FPS to 60
|
||||
"geo.enabled" = false;
|
||||
"media.peerconnection.enabled" = false; # Prevents WebRTC IP leaks
|
||||
"network.dns.disablePrefetch" = true;
|
||||
"network.prefetch-next" = false;
|
||||
|
||||
# --- NixOS / Hyprland Integration ---
|
||||
"widget.use-xdg-desktop-portal.file-picker" = 1; # Use native file picker
|
||||
|
||||
# --- UI & Behavior ---
|
||||
"browser.toolbars.bookmarks.visibility" = "never";
|
||||
"browser.compactmode.show" = true;
|
||||
"browser.tabs.closeWindowWithLastTab" = false;
|
||||
"extensions.pocket.enabled" = false;
|
||||
"extensions.screenshots.disabled" = true;
|
||||
"browser.topsites.contile.enabled" = false;
|
||||
"browser.formfill.enable" = false;
|
||||
"browser.search.suggest.enabled" = false;
|
||||
"browser.search.suggest.enabled.private" = false;
|
||||
"browser.urlbar.suggest.searches" = false;
|
||||
"browser.urlbar.showSearchSuggestionsFirst" = false;
|
||||
"browser.newtabpage.activity-stream.feeds.section.topstories" = false;
|
||||
"browser.newtabpage.activity-stream.feeds.snippets" = false;
|
||||
"browser.newtabpage.activity-stream.section.highlights.includePocket" = false;
|
||||
"browser.newtabpage.activity-stream.section.highlights.includeBookmarks" = false;
|
||||
"browser.newtabpage.activity-stream.section.highlights.includeDownloads" = false;
|
||||
"browser.newtabpage.activity-stream.section.highlights.includeVisited" = false;
|
||||
"browser.newtabpage.activity-stream.showSponsored" = false;
|
||||
"browser.newtabpage.activity-stream.system.showSponsored" = false;
|
||||
"browser.newtabpage.activity-stream.showSponsoredTopSites" = false;
|
||||
"toolkit.legacyUserProfileCustomizations.stylesheets" = true;
|
||||
"extensions.autoDisableScopes" = 0; # Enable extensions by default
|
||||
|
||||
# --- Homepage & Navigation ---
|
||||
"browser.startup.page" = 1; # Always open the homepage
|
||||
"browser.startup.homepage" = url;
|
||||
"browser.newtab.url" = url; # Try to set newtab to homepage
|
||||
"browser.sessionstore.resume_from_crash" = false; # Always start fresh
|
||||
"browser.sessionstore.max_tabs_undo" = 0; # Disable undo close tab
|
||||
|
||||
# --- DNS over HTTPS (Quad9) ---
|
||||
"network.trr.mode" = 2; # Use DoH with system fallback
|
||||
"network.trr.uri" = "https://dns.quad9.net/dns-query";
|
||||
};
|
||||
#
|
||||
# userChrome = ''
|
||||
# /* --- Autohide Entire Toolbox (Tabs + Address Bar) --- */
|
||||
# /* Adapted from MrOtherGuy's autohide_main_toolbar.css */
|
||||
#
|
||||
# :root{
|
||||
# /* Height of Tabs + Nav Bar approx 80px */
|
||||
# --uc-navbar-transform: -85px;
|
||||
# --uc-autohide-toolbar-delay: 0.1s;
|
||||
# --uc-autohide-toolbar-duration: 200ms;
|
||||
# }
|
||||
# :root[uidensity="compact"]{ --uc-navbar-transform: -70px }
|
||||
#
|
||||
# #navigator-toolbox > div{ display: contents; }
|
||||
#
|
||||
# /* Apply transform to TabsToolbar AND Nav-bar */
|
||||
# :root[sessionrestored] :where(#nav-bar,#PersonalToolbar,#TabsToolbar,#tab-notification-deck,.global-notificationbox,#notifications-toolbar){
|
||||
# transform: translateY(var(--uc-navbar-transform))
|
||||
# }
|
||||
#
|
||||
# :root:is([customizing],[chromehidden*="toolbar"]) :where(#nav-bar,#PersonalToolbar,#TabsToolbar,#tab-notification-deck,.global-notificationbox,#notifications-toolbar){
|
||||
# transform: none !important;
|
||||
# opacity: 1 !important;
|
||||
# }
|
||||
#
|
||||
# /* Hide styles for Nav-Bar AND TabsToolbar */
|
||||
# :where(#nav-bar,#TabsToolbar):not([customizing]){
|
||||
# opacity: 0;
|
||||
# transition: transform var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay), opacity var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay) !important;
|
||||
# position: relative;
|
||||
# z-index: 2;
|
||||
# background-color: #1c1b22 !important; /* Solid background */
|
||||
# }
|
||||
#
|
||||
# #navigator-toolbox,
|
||||
# #sidebar-box,
|
||||
# #sidebar-main,
|
||||
# #sidebar-splitter,
|
||||
# #tabbrowser-tabbox{
|
||||
# z-index: auto !important;
|
||||
# }
|
||||
#
|
||||
# /* Show when toolbox is focused or hovered */
|
||||
# #navigator-toolbox:focus-within > .browser-toolbar,
|
||||
# .browser-titlebar:hover ~ :is(#nav-bar,#PersonalToolbar,#TabsToolbar),
|
||||
# #nav-bar:hover,
|
||||
# #TabsToolbar:hover,
|
||||
# #nav-bar:hover + #PersonalToolbar{
|
||||
# transform: translateY(0);
|
||||
# opacity: 1;
|
||||
# transition-duration: var(--uc-autohide-toolbar-duration), var(--uc-autohide-toolbar-duration) !important;
|
||||
# transition-delay: 0s !important;
|
||||
# }
|
||||
#
|
||||
# /* Ensure popups still work (URL bar) */
|
||||
# :root[sessionrestored] #urlbar[popover]{
|
||||
# opacity: 0;
|
||||
# pointer-events: none;
|
||||
# transition: transform var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay), opacity var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay);
|
||||
# transform: translateY(var(--uc-navbar-transform));
|
||||
# }
|
||||
# #mainPopupSet:has(> [panelopen]:not(#ask-chat-shortcuts,#selection-shortcut-action-panel,#chat-shortcuts-options-panel,#tab-preview-panel)) ~ toolbox #urlbar[popover],
|
||||
# .browser-titlebar:is(:hover,:focus-within) ~ #nav-bar #urlbar[popover],
|
||||
# #nav-bar:is(:hover,:focus-within) #urlbar[popover],
|
||||
# #urlbar-container > #urlbar[popover]:is([focused],[open]){
|
||||
# opacity: 1;
|
||||
# pointer-events: auto;
|
||||
# transition-delay: 0ms;
|
||||
# transform: translateY(0);
|
||||
# }
|
||||
# :where(:root[sessionrestored]) #urlbar-container > #urlbar[popover]:is([focused],[open]){
|
||||
# transition-duration: 100ms;
|
||||
# }
|
||||
#
|
||||
# /* --- CRITICAL FIX: Trigger Zone --- */
|
||||
# /* Since we hide EVERYTHING, we need a hitbox at the top of the screen */
|
||||
# #navigator-toolbox::after {
|
||||
# content: "";
|
||||
# position: fixed;
|
||||
# top: 0;
|
||||
# left: 0;
|
||||
# width: 100%;
|
||||
# height: 20px; /* Generous hit target */
|
||||
# z-index: 10000;
|
||||
# pointer-events: auto;
|
||||
# }
|
||||
#
|
||||
# /* When hitbox is hovered, reveal bars */
|
||||
# #navigator-toolbox:hover :where(#nav-bar,#PersonalToolbar,#TabsToolbar) {
|
||||
# transform: translateY(0) !important;
|
||||
# opacity: 1 !important;
|
||||
# transition-delay: 0s !important;
|
||||
# }
|
||||
#
|
||||
# /* Move up the content view to fill the gap */
|
||||
# :root[sessionrestored]:not([chromehidden~="toolbar"]) > body > #browser{
|
||||
# margin-top: var(--uc-navbar-transform);
|
||||
# }
|
||||
#
|
||||
# /* Fix Titlebar and Bookmarks */
|
||||
# #titlebar { appearance: none !important; }
|
||||
# #PersonalToolbar { visibility: collapse !important; }
|
||||
# '';
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
textfox = {
|
||||
enable = true;
|
||||
profiles = ["hakase" "web-app"];
|
||||
config = {
|
||||
# background = {
|
||||
# color = "#123456";
|
||||
# };
|
||||
# border = {
|
||||
# color = "#654321";
|
||||
# width = "4px";
|
||||
# transition = "1.0s ease";
|
||||
# radius = "3px";
|
||||
# };
|
||||
# displayWindowControls = true;
|
||||
# displayNavButtons = true;
|
||||
# displayUrlbarIcons = true;
|
||||
# displaySidebarTools = false;
|
||||
displayTitles = true;
|
||||
# newtabLogo = " __ __ ____ \A / /____ _ __/ /_/ __/___ _ __\A / __/ _ \\| |/_/ __/ /_/ __ \\| |/_/\A / /_/ __/> </ /_/ __/ /_/ /> < \A \\__/\\___/_/|_|\\__/_/ \\____/_/|_| ";
|
||||
# font = {
|
||||
# family = "Fira Code";
|
||||
# size = "15px";
|
||||
# accent = "#654321";
|
||||
# };
|
||||
tabs = {
|
||||
horizontal.enable = false;
|
||||
# horizontal.enable = true;
|
||||
# vertical.enable = true;
|
||||
# vertical.margin = "1.0rem";
|
||||
};
|
||||
# navbar = {
|
||||
# margin = "8px 8px 2px";
|
||||
# padding = "4px";
|
||||
# };
|
||||
bookmarks = {
|
||||
alignment = "left";
|
||||
};
|
||||
# icons = {
|
||||
# toolbar.extensions.enable = true;
|
||||
# context.extensions.enable = true;
|
||||
# context.firefox.enable = true;
|
||||
# };
|
||||
# textTransform = "uppercase";
|
||||
# extraConfig = "/* custom css here */";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,18 +1,17 @@
|
||||
{
|
||||
pkgs,
|
||||
terminal,
|
||||
myConfig,
|
||||
...
|
||||
}: {
|
||||
programs.zoxide.enable = true;
|
||||
programs.fish = {
|
||||
enable = true;
|
||||
interactiveShellInit = ''
|
||||
set fish_greeting
|
||||
fish_vi_key_bindings
|
||||
zoxide init fish | source
|
||||
|
||||
zoxide init fish --cmd cd | source
|
||||
'';
|
||||
shellAliases = terminal.shellAliases;
|
||||
shellAliases = myConfig.terminal.aliases;
|
||||
|
||||
plugins = with pkgs.fishPlugins; [
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
{pkgs, ...}: {
|
||||
home.packages = with pkgs; [
|
||||
gemini-cli
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
myConfig,
|
||||
...
|
||||
}: {
|
||||
home.packages = [
|
||||
# TODO: will rewrite later
|
||||
(pkgs.writeShellScriptBin "tte-loop" ''
|
||||
trap 'printf "\e[?25h"; exit 0' INT
|
||||
printf '\e[?25l'
|
||||
effects=(beams binarypath blackhole bouncyballs bubbles burn colorshift crumble decrypt errorcorrect expand fireworks highlight laseretch matrix middleout orbittingvolley overflow pour print rain randomsequence rings scattered slice slide spotlights spray swarm sweep synthgrid unstable vhstape waves wipe)
|
||||
while true; do
|
||||
clear
|
||||
cols=$(tput cols)
|
||||
lines=$(tput lines)
|
||||
effect="''${effects[RANDOM % ''${#effects[@]}]}"
|
||||
printf '\e[?25l'
|
||||
${pkgs.terminaltexteffects}/bin/tte --input-file ${config.home.homeDirectory}/.config/nixos/assets/branding.txt --anchor-canvas c --anchor-text c --canvas-width "$cols" --canvas-height "$((lines-2))" --frame-rate 120 "$effect"
|
||||
printf '\e[?25l'
|
||||
sleep 2
|
||||
done
|
||||
'')
|
||||
(pkgs.writeShellScriptBin "tte-screensaver" ''
|
||||
# Get all monitors
|
||||
monitors=$(${pkgs.hyprland}/bin/hyprctl monitors -j | ${pkgs.jq}/bin/jq -r '.[].name')
|
||||
|
||||
# Launch ghostty on each monitor one at a time
|
||||
for monitor in $monitors; do
|
||||
${pkgs.hyprland}/bin/hyprctl dispatch focusmonitor "$monitor"
|
||||
sleep 0.3
|
||||
${pkgs.ghostty}/bin/ghostty --config-file=${config.home.homeDirectory}/.config/ghostty/screensaver --fullscreen -e tte-loop &
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Monitor for any input and exit when detected
|
||||
${pkgs.libinput}/bin/libinput debug-events 2>/dev/null | head -n 1 >/dev/null
|
||||
|
||||
# Input detected, kill all screensaver instances
|
||||
${pkgs.procps}/bin/pkill -f "ghostty.*tte-loop"
|
||||
'')
|
||||
];
|
||||
|
||||
home.file.".config/ghostty/screensaver".text = ''
|
||||
window-padding-x = 0
|
||||
window-padding-y = 0
|
||||
window-padding-color = "extend-always"
|
||||
'';
|
||||
programs.ghostty = {
|
||||
enable = true;
|
||||
package =
|
||||
if pkgs.stdenv.isDarwin
|
||||
then pkgs.ghostty-bin
|
||||
else pkgs.ghostty;
|
||||
enableFishIntegration = true;
|
||||
|
||||
settings = {
|
||||
font-family = myConfig.terminal.font;
|
||||
confirm-close-surface = false;
|
||||
app-notifications = false;
|
||||
window-padding-x = 15;
|
||||
window-padding-y = 15;
|
||||
window-padding-balance = true;
|
||||
gtk-titlebar = false;
|
||||
mouse-hide-while-typing = true;
|
||||
copy-on-select = "clipboard";
|
||||
auto-update = "off";
|
||||
};
|
||||
};
|
||||
|
||||
wayland.windowManager.hyprland.settings.bindd = [
|
||||
"SUPER, P, Toggle Preload, togglespecialworkspace, preload"
|
||||
"SUPER SHIFT, P, Move to Preload Special Workspace, movetoworkspace, special:preload"
|
||||
];
|
||||
|
||||
wayland.windowManager.hyprland.settings.exec-once = [
|
||||
"[workspace special:preload silent] uwsm app -- xdg-terminal-exec"
|
||||
"[workspace 1] uwsm app -- ghostty -e bash -c 'fastfetch; exec $SHELL'" # TODO: must be xdg-terminal-exec, or default user terminal
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{myConfig, ...}: {
|
||||
programs.git = {
|
||||
enable = true;
|
||||
settings = {
|
||||
user.name = "${myConfig.git.username}";
|
||||
user.email = "${myConfig.git.email}";
|
||||
init.defaultBranch = "${myConfig.git.defaultBranch}";
|
||||
};
|
||||
};
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
includes = [
|
||||
"/run/secrets/ssh_extra_config"
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{pkgs, ...}: {
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
exec-once = [
|
||||
"uwsm app -- hypridle"
|
||||
];
|
||||
};
|
||||
services.hypridle = {
|
||||
enable = true;
|
||||
settings = {
|
||||
general = {
|
||||
after_sleep_cmd = "hyprctl dispatch dpms on";
|
||||
ignore_dbus_inhibit = false;
|
||||
lock_cmd = "hakase-hyprlock";
|
||||
before_sleep_cmd = "hakase-hyprlock"; # lock before suspend
|
||||
};
|
||||
|
||||
listener = [
|
||||
# {
|
||||
# timeout = 180; # 3min
|
||||
# on-timeout = "tte-screensaver";
|
||||
# }
|
||||
{
|
||||
timeout = 300; # 5min
|
||||
on-timeout = "hakase-hyprlock"; # lock screen when timeout has passed
|
||||
}
|
||||
{
|
||||
timeout = 330; # 5.5min
|
||||
on-timeout = "hyprctl dispatch dpms off"; # screen off when timeout has passed
|
||||
on-resume = "hyprctl dispatch dpms on"; # screen on when activity is detected after timeout has passed
|
||||
}
|
||||
{
|
||||
timeout = 660;
|
||||
on-timeout = "systemctl suspend"; # suspend pc
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
./hypr/animation.nix
|
||||
./hypr/binds.nix
|
||||
./hypr/exec.nix
|
||||
./hypr/general.nix
|
||||
./hypr/input.nix
|
||||
./hypr/layers.nix
|
||||
./hypr/misc.nix
|
||||
./hypr/rules.nix
|
||||
|
||||
./scripts/movement.nix
|
||||
./scripts/workspace-toggle.nix
|
||||
];
|
||||
wayland.windowManager.hyprland.enable = true;
|
||||
wayland.windowManager.hyprland.systemd.enable = false; # for UWSM support...
|
||||
wayland.windowManager.hyprland.plugins = [
|
||||
pkgs.hyprlandPlugins.hyprsplit
|
||||
pkgs.hyprlandPlugins.hypr-dynamic-cursors
|
||||
pkgs.hyprlandPlugins.hyprspace
|
||||
pkgs.hyprlandPlugins.hyprbars
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
animations = {
|
||||
enabled = true;
|
||||
|
||||
bezier = [
|
||||
"easeOutQuint,0.23,1,0.32,1"
|
||||
"easeInOutCubic,0.65,0.05,0.36,1"
|
||||
"linear,0,0,1,1"
|
||||
"almostLinear,0.5,0.5,0.75,1.0"
|
||||
"quick,0.15,0,0.1,1"
|
||||
];
|
||||
|
||||
animation = [
|
||||
"global, 1, 10, default"
|
||||
"border, 1, 5.39, easeOutQuint"
|
||||
"windows, 1, 4.79, easeOutQuint"
|
||||
"windowsIn, 1, 4.1, easeOutQuint, popin 87%"
|
||||
"windowsOut, 1, 1.49, linear, popin 87%"
|
||||
"fadeIn, 1, 1.73, almostLinear"
|
||||
"fadeOut, 1, 1.46, almostLinear"
|
||||
"fade, 1, 3.03, quick"
|
||||
"layers, 1, 3.81, easeOutQuint"
|
||||
"layersIn, 1, 4, easeOutQuint, fade"
|
||||
"layersOut, 1, 1.5, linear, fade"
|
||||
"fadeLayersIn, 1, 1.79, almostLinear"
|
||||
"fadeLayersOut, 1, 1.39, almostLinear"
|
||||
"workspaces, 0, 0, ease"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
{pkgs, ...}: {
|
||||
# TODO: implement a way to show binds, preferably use vicinae.
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
binds = {
|
||||
workspace_back_and_forth = true;
|
||||
};
|
||||
bindel = [
|
||||
", XF86MonBrightnessUp, exec, ddcutil setvcp 10 + 10"
|
||||
", XF86MonBrightnessDown, exec, ddcutil setvcp 10 - 10"
|
||||
];
|
||||
bindm = [
|
||||
"SUPER, mouse:272, movewindow"
|
||||
"SUPER, mouse:273, resizewindow"
|
||||
];
|
||||
|
||||
bindd =
|
||||
[
|
||||
# essential
|
||||
"SUPER, Return, Open Terminal, exec, uwsm app -- xdg-terminal-exec"
|
||||
"SUPER, Q, Kill active, killactive"
|
||||
|
||||
# resize
|
||||
"SUPER CTRL, H, Resize Left, resizeactive, -40 0"
|
||||
"SUPER CTRL, J, Resize Down, resizeactive, 0 40"
|
||||
"SUPER CTRL, K, Resize Up, resizeactive, 0 -40"
|
||||
"SUPER CTRL, L, Resize Right, resizeactive, 40 0"
|
||||
|
||||
# move focus
|
||||
"SUPER, J, Move focus down, movefocus, d"
|
||||
"SUPER, K, Move focus up, movefocus, u"
|
||||
"SUPER, H, Move focus left, movefocus, l"
|
||||
"SUPER, L, Move focus right, movefocus, r"
|
||||
"SUPER, G, Switch Focus (Float/Tile), exec, hakase-focus-switch"
|
||||
|
||||
# move window
|
||||
"SUPER SHIFT, h, Move window left, movewindow, l"
|
||||
"SUPER SHIFT, j, Move window down, movewindow, d"
|
||||
"SUPER SHIFT, k, Move window up, movewindow, u"
|
||||
"SUPER SHIFT, l, Move window right, movewindow, r"
|
||||
|
||||
# fullscreen
|
||||
"SUPER, F, Toggle Fullscreen, fullscreen, 0"
|
||||
"SUPER SHIFT, F, Toggle Maximized Fullscreen, fullscreen, 1"
|
||||
|
||||
# layout
|
||||
"SUPER, O, Toggle Split, layoutmsg, togglesplit"
|
||||
|
||||
# apps
|
||||
# "SUPER, SPACE, Open App Launcher, exec, nc -U $XDG_RUNTIME_DIR/walker/walker.sock"
|
||||
|
||||
# TODO:
|
||||
# add screen recording
|
||||
|
||||
# Special workspace
|
||||
"SUPER, U, Toggle Special Workspace, togglespecialworkspace, custom"
|
||||
"SUPER SHIFT, U, Move to Special Workspace, movetoworkspace, special:custom"
|
||||
|
||||
# [Workspaces] Toggle between most recent workspaces
|
||||
"SUPER, Tab, Cycle workspaces, workspace, previous"
|
||||
|
||||
# [Workspaces] Move to another workspace
|
||||
"CTRL SHIFT, H, Move to previous workspace, split:workspace, -1"
|
||||
"CTRL SHIFT, L, Move to next workspace, split:workspace, +1"
|
||||
"CTRL SHIFT, K, Move to previous workspace, split:workspace, -1"
|
||||
"CTRL SHIFT, J, Move to next workspace, split:workspace, +1"
|
||||
|
||||
# hyprspace - workspace overview
|
||||
"SUPER, E, Toggle Workspace Overview, overview:toggle"
|
||||
]
|
||||
++ (
|
||||
# Generate binds for Super + [1-5] to switch workspaces with special workspace toggle support
|
||||
# and Super + Shift + [1-5] to move window to workspace on current monitor
|
||||
builtins.concatLists (builtins.genList (
|
||||
i: let
|
||||
ws = i + 1;
|
||||
key = toString ws;
|
||||
in [
|
||||
"SUPER, ${key}, Switch to workspace ${toString ws}, exec, workspace-toggle ${toString ws}"
|
||||
"SUPER SHIFT, ${key}, Move window to workspace ${toString ws}, split:movetoworkspace, ${toString ws}"
|
||||
]
|
||||
)
|
||||
5)
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{pkgs, ...}: {
|
||||
home.packages = [
|
||||
pkgs.gum
|
||||
];
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
env = [
|
||||
"GUM_CONFIRM_PROMPT_FOREGROUND,6"
|
||||
"GUM_CONFIRM_SELECTED_FOREGROUND,0"
|
||||
"GUM_CONFIRM_SELECTED_BACKGROUND,2"
|
||||
"GUM_CONFIRM_UNSELECTED_FOREGROUND,0"
|
||||
"GUM_CONFIRM_UNSELECTED_BACKGROUND,8"
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}: {
|
||||
home.packages = with pkgs; [
|
||||
psmisc
|
||||
];
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
exec = [
|
||||
# "pkill -x hyprpaper; uwsm app -- hyprpaper"
|
||||
# "matugen image ${config.home.homeDirectory}/.cache/current_wallpaper"
|
||||
];
|
||||
exec-once = [
|
||||
# essentials
|
||||
"hyprpm reload -n"
|
||||
"systemctl --user start hyprpolkitagent"
|
||||
"systemctl --user start swayosd"
|
||||
# "hyprsunset -t 4500" # TODO: must be optional
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{myConfig, ...}: {
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
general = {
|
||||
gaps_in = 5;
|
||||
gaps_out = 15;
|
||||
layout = "dwindle";
|
||||
allow_tearing = true;
|
||||
resize_on_border = true;
|
||||
};
|
||||
decoration = {
|
||||
rounding = 0;
|
||||
active_opacity = 0.99;
|
||||
inactive_opacity = 0.99;
|
||||
shadow = {
|
||||
enabled = true;
|
||||
range = 2;
|
||||
render_power = 3;
|
||||
color = "rgba(1a1a1aee)";
|
||||
};
|
||||
blur = {
|
||||
enabled = true;
|
||||
size = 8;
|
||||
passes = 2;
|
||||
new_optimizations = true;
|
||||
special = true;
|
||||
brightness = 0.60;
|
||||
contrast = 0.75;
|
||||
};
|
||||
};
|
||||
monitor = myConfig.hyprland.monitors;
|
||||
dwindle = {
|
||||
pseudotile = true;
|
||||
preserve_split = true;
|
||||
smart_split = false;
|
||||
};
|
||||
master = {
|
||||
new_status = "master";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{myConfig, ...}: {
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
input = {
|
||||
repeat_rate = 50;
|
||||
repeat_delay = 300;
|
||||
numlock_by_default = true;
|
||||
kb_options = myConfig.hyprland.kb_options;
|
||||
};
|
||||
cursor = {
|
||||
hide_on_key_press = false;
|
||||
no_warps = false;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{pkgs, ...}: {
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
layerrule = [
|
||||
# Blur and transparency for vicinae
|
||||
"blur, vicinae"
|
||||
"ignorealpha 0, vicinae"
|
||||
|
||||
# Disable animation for vicinae
|
||||
"noanim, vicinae"
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
{myConfig, ...}: {
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
misc = {
|
||||
disable_hyprland_logo = true;
|
||||
disable_splash_rendering = true;
|
||||
focus_on_activate = true;
|
||||
anr_missed_pings = 3;
|
||||
new_window_takes_over_fullscreen = 1;
|
||||
};
|
||||
|
||||
# experimental = {
|
||||
# hdr = true;
|
||||
# };
|
||||
|
||||
cursor = {
|
||||
no_hardware_cursors = true;
|
||||
no_break_fs_vrr = true;
|
||||
min_refresh_rate = 48;
|
||||
};
|
||||
|
||||
render = {
|
||||
direct_scanout = true;
|
||||
cm_enabled = true;
|
||||
};
|
||||
|
||||
plugin = {
|
||||
hyprsplit = {
|
||||
num_workspaces = 5;
|
||||
persistent_workspaces = false;
|
||||
};
|
||||
|
||||
dynamic-cursors = {
|
||||
mode = "tilt";
|
||||
shake = {
|
||||
enabled = true;
|
||||
threshold = 4.0;
|
||||
limit = 4.0;
|
||||
timeout = 200;
|
||||
};
|
||||
};
|
||||
|
||||
overview = {
|
||||
# Using default settings
|
||||
};
|
||||
|
||||
hyprbars = {
|
||||
bar_height = 24;
|
||||
bar_color = "$surface_container_high";
|
||||
bar_text_color = "$on_surface";
|
||||
bar_text_size = 0;
|
||||
bar_text_font = myConfig.font.sans;
|
||||
bar_button_padding = 4;
|
||||
bar_padding = 8;
|
||||
bar_precedence_over_border = true;
|
||||
on_double_click = "hyprctl dispatch fullscreen 1";
|
||||
hyprbars-button = [
|
||||
"$error, 10, , hyprctl dispatch killactive"
|
||||
"$tertiary, 10, , hyprctl dispatch fullscreen 1"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
windowrulev2 = [
|
||||
# Make all inactive windows transparent
|
||||
"opacity 0.99 0.8, class:.*"
|
||||
# But make Firefox windows opaque again (last rule wins)
|
||||
"float, title:(?i)bitwarden"
|
||||
];
|
||||
workspace = [
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{pkgs, ...}: let
|
||||
hakase-workspace-switch-force = pkgs.writeShellScriptBin "hakase-workspace-switch-force" ''
|
||||
HYPRCTL="${pkgs.hyprland}/bin/hyprctl"
|
||||
JQ="${pkgs.jq}/bin/jq"
|
||||
|
||||
special_workspace=$($HYPRCTL monitors -j | $JQ -r '.[] | select(.focused) | .specialWorkspace.name')
|
||||
|
||||
workspace_name=''${special_workspace#*:}
|
||||
|
||||
chosen_workspace_num=$1
|
||||
|
||||
if [[ -z ''${chosen_workspace_num} ]]; then
|
||||
echo "Usage: $(basename "$0") [number]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "''${special_workspace}" == *"special"* ]]; then
|
||||
echo "[LOG] workspace is ''${special_workspace}"
|
||||
|
||||
$HYPRCTL dispatch togglespecialworkspace "''${workspace_name}"
|
||||
|
||||
$HYPRCTL dispatch workspace "''${chosen_workspace_num}"
|
||||
else
|
||||
echo "[LOG] workspace is not special"
|
||||
$HYPRCTL dispatch workspace "''${chosen_workspace_num}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exit 0
|
||||
'';
|
||||
|
||||
# TODO: revise
|
||||
hakase-focus-switch = pkgs.writeShellScriptBin "hakase-focus-switch" ''
|
||||
HYPRCTL="${pkgs.hyprland}/bin/hyprctl"
|
||||
JQ="${pkgs.jq}/bin/jq"
|
||||
|
||||
workspace_id=$($HYPRCTL activeworkspace -j | $JQ '.id')
|
||||
active_window=$($HYPRCTL activewindow -j)
|
||||
is_floating=$(echo "$active_window" | $JQ '.floating')
|
||||
|
||||
if [ "$is_floating" == "true" ]; then
|
||||
target_addr=$($HYPRCTL clients -j | $JQ -r --argjson ws "$workspace_id" '[.[] | select(.workspace.id == $ws and .floating == false)] | .[0].address')
|
||||
else
|
||||
target_addr=$($HYPRCTL clients -j | $JQ -r --argjson ws "$workspace_id" '[.[] | select(.workspace.id == $ws and .floating == true)] | .[0].address')
|
||||
fi
|
||||
|
||||
if [ "$target_addr" != "null" ] && [ -n "$target_addr" ]; then
|
||||
$HYPRCTL dispatch focuswindow address:$target_addr
|
||||
fi
|
||||
'';
|
||||
in {
|
||||
home.packages = [
|
||||
hakase-workspace-switch-force
|
||||
hakase-focus-switch
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{pkgs, ...}: let
|
||||
workspace-toggle = pkgs.writeShellScriptBin "workspace-toggle" ''
|
||||
#!/usr/bin/env bash
|
||||
target_workspace="$1"
|
||||
|
||||
# Get current workspace info
|
||||
current_info=$(${pkgs.hyprland}/bin/hyprctl activeworkspace -j)
|
||||
current=$(echo "$current_info" | ${pkgs.jq}/bin/jq -r '.id')
|
||||
|
||||
# Check if we're in a special workspace (negative ID)
|
||||
if [[ $current -lt 0 ]]; then
|
||||
# We're in a special workspace, force switch to target workspace
|
||||
${pkgs.hyprland}/bin/hyprctl dispatch focusworkspaceoncurrentmonitor "$target_workspace"
|
||||
elif [[ $current -eq $target_workspace ]]; then
|
||||
# We're already on the target workspace, toggle back to previous
|
||||
${pkgs.hyprland}/bin/hyprctl dispatch workspace previous
|
||||
else
|
||||
# We're on a different normal workspace, switch to target using split:workspace
|
||||
${pkgs.hyprland}/bin/hyprctl dispatch split:workspace "$target_workspace"
|
||||
fi
|
||||
'';
|
||||
in {
|
||||
home.packages = [workspace-toggle];
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
myConfig,
|
||||
...
|
||||
}: let
|
||||
cacheWallpaper = "${config.home.homeDirectory}/.cache/current_wallpaper";
|
||||
clockFont = myConfig.font.monospace;
|
||||
scriptFont = myConfig.font.monospaceScript;
|
||||
greetingConf = "${config.home.homeDirectory}/.cache/hyprlock-greeting.conf";
|
||||
|
||||
hakase-hyprlock = pkgs.writeShellScriptBin "hakase-hyprlock" ''
|
||||
# Get focused monitor
|
||||
monitor=$(hyprctl monitors -j | ${pkgs.jq}/bin/jq -r '.[] | select(.focused) | .name')
|
||||
|
||||
# Generate greeting label config
|
||||
cat > ${greetingConf} << EOF
|
||||
label {
|
||||
monitor = $monitor
|
||||
text = cmd[update:200] hakase-hyprlock-typewriter "\$(hakase-hyprlock-text-generator)"
|
||||
color = \$on_surface_variant
|
||||
font_size = 120
|
||||
font_family = ${clockFont} Bold
|
||||
position = 0, 480
|
||||
halign = center
|
||||
valign = center
|
||||
}
|
||||
EOF
|
||||
|
||||
exec hyprlock "$@"
|
||||
'';
|
||||
in {
|
||||
imports = [
|
||||
./scripts/typewriter.nix
|
||||
./scripts/random-text.nix
|
||||
];
|
||||
home.packages = [hakase-hyprlock];
|
||||
programs.hyprlock = {
|
||||
enable = true;
|
||||
extraConfig = ''
|
||||
source = ~/.config/hypr/hyprlock-colors.conf
|
||||
source = ${greetingConf}
|
||||
|
||||
general {
|
||||
hide_cursor = true
|
||||
grace = 0
|
||||
}
|
||||
|
||||
background {
|
||||
monitor =
|
||||
path = ${cacheWallpaper}
|
||||
blur_passes = 3
|
||||
blur_size = 8
|
||||
contrast = 0.9
|
||||
brightness = 0.7
|
||||
vibrancy = 0.2
|
||||
}
|
||||
|
||||
# Hours (top)
|
||||
label {
|
||||
monitor =
|
||||
text = cmd[update:1000] date +%H
|
||||
color = $on_surface
|
||||
font_size = 140
|
||||
font_family = ${clockFont} Bold
|
||||
position = 0, 80
|
||||
halign = center
|
||||
valign = center
|
||||
}
|
||||
|
||||
# Minutes (bottom)
|
||||
label {
|
||||
monitor =
|
||||
text = cmd[update:1000] date +%M
|
||||
color = $primary
|
||||
font_size = 140
|
||||
font_family = ${clockFont} Bold
|
||||
position = 0, -80
|
||||
halign = center
|
||||
valign = center
|
||||
}
|
||||
|
||||
# Date
|
||||
label {
|
||||
monitor =
|
||||
text = cmd[update:60000] echo "<span font_features='ss02'>$(date '+%A, %B %d')</span>"
|
||||
color = $on_surface_variant
|
||||
font_size = 18
|
||||
font_family = ${clockFont} Italic
|
||||
position = 0, -320
|
||||
halign = center
|
||||
valign = center
|
||||
}
|
||||
|
||||
# Caps Lock indicator (above input)
|
||||
label {
|
||||
monitor =
|
||||
text = cmd[update:100] cat /sys/class/leds/*capslock*/brightness 2>/dev/null | grep -q 1 && echo 'CAPS LOCK'
|
||||
color = $tertiary
|
||||
font_size = 12
|
||||
font_family = ${clockFont}
|
||||
position = 0, -210
|
||||
halign = center
|
||||
valign = center
|
||||
}
|
||||
|
||||
input-field {
|
||||
monitor =
|
||||
size = 300, 50
|
||||
outline_thickness = 3
|
||||
dots_size = 0.33
|
||||
dots_spacing = 0.15
|
||||
dots_center = true
|
||||
outer_color = $primary
|
||||
inner_color = $surface
|
||||
font_color = $on_surface
|
||||
fade_on_empty = false
|
||||
placeholder_text = <i>Password...</i>
|
||||
hide_input = false
|
||||
rounding = 15
|
||||
position = 0, -250
|
||||
halign = center
|
||||
valign = center
|
||||
|
||||
# Auth feedback
|
||||
check_color = $secondary
|
||||
fail_color = $error
|
||||
fail_text = <i>$FAIL</i> <b>($ATTEMPTS)</b>
|
||||
fail_timeout = 2000
|
||||
fail_transition = 300
|
||||
}
|
||||
|
||||
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
{pkgs, ...}: let
|
||||
hakase-hyprlock-text-generator = pkgs.writeShellScriptBin "hakase-hyprlock-text-generator" ''
|
||||
cache_file="''${XDG_RUNTIME_DIR:-/tmp}/hyprlock_greeting"
|
||||
pid_file="''${XDG_RUNTIME_DIR:-/tmp}/hyprlock_greeting_pid"
|
||||
|
||||
current_pid=$(pgrep -x hyprlock | head -1)
|
||||
|
||||
# Pick new greeting only when hyprlock restarts
|
||||
if [[ -f $pid_file && -f $cache_file ]]; then
|
||||
old_pid=$(cat "$pid_file")
|
||||
if [[ "$old_pid" == "$current_pid" ]]; then
|
||||
cat "$cache_file"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
greetings=(
|
||||
"Hello"
|
||||
"Hola"
|
||||
"Bonjour"
|
||||
"Hallo"
|
||||
"Ciao"
|
||||
"Olá"
|
||||
"Привет"
|
||||
"こんにちは"
|
||||
"你好"
|
||||
"안녕하세요"
|
||||
"مرحبا"
|
||||
"שלום"
|
||||
"नमस्ते"
|
||||
"สวัสดี"
|
||||
"Γειά σου"
|
||||
"Merhaba"
|
||||
"Xin chào"
|
||||
"Cześć"
|
||||
"Hej"
|
||||
"Ahoj"
|
||||
"Szia"
|
||||
"Salut"
|
||||
"Привіт"
|
||||
"হ্যালো"
|
||||
"வணக்கம்"
|
||||
"Jambo"
|
||||
"Aloha"
|
||||
"Sawubona"
|
||||
"Hei"
|
||||
"Hallå"
|
||||
"Kamusta"
|
||||
"Salam"
|
||||
"Selamat"
|
||||
"Saluton"
|
||||
"Tere"
|
||||
"Sveiki"
|
||||
"Labas"
|
||||
"Здраво"
|
||||
"Здравей"
|
||||
"Bok"
|
||||
"Përshëndetje"
|
||||
"Բարև"
|
||||
"გამარჯობა"
|
||||
"Сайн уу"
|
||||
"ສະບາຍດີ"
|
||||
"ជំរាបសួរ"
|
||||
"မင်္ဂလာပါ"
|
||||
"ආයුබෝවන්"
|
||||
"Dia dhuit"
|
||||
"Halò"
|
||||
"Shwmae"
|
||||
"Hoi"
|
||||
"Halló"
|
||||
"Kaixo"
|
||||
"Bon dia"
|
||||
"Ola"
|
||||
"Ħello"
|
||||
"ਸਤਿ ਸ਼੍ਰੀ ਅਕਾਲ"
|
||||
"કેમ છો"
|
||||
"नमस्कार"
|
||||
"ನಮಸ್ಕಾರ"
|
||||
"നമസ്കാരം"
|
||||
"నమస్కారం"
|
||||
"ሰላም"
|
||||
"Bawo"
|
||||
"Ndeewo"
|
||||
"Sannu"
|
||||
"Iska warran"
|
||||
"Kia ora"
|
||||
"Bula"
|
||||
"Talofa"
|
||||
"Mālō e lelei"
|
||||
"ᐊᐃᖓᐃ"
|
||||
"ᎣᏏᏲ"
|
||||
"Yá'át'ééh"
|
||||
"Allinllachu"
|
||||
"Mba'éichapa"
|
||||
"Salve"
|
||||
"Moien"
|
||||
"Apa khabar"
|
||||
"Сәлем"
|
||||
"Assalomu alaykum"
|
||||
"Slav"
|
||||
"བཀྲ་ཤིས་བདེ་ལེགས།"
|
||||
)
|
||||
|
||||
inspirations=(
|
||||
"Dream Big"
|
||||
"Stay True"
|
||||
"Be Kind"
|
||||
"Work Hard"
|
||||
"Keep Going"
|
||||
"Be Brave"
|
||||
"Love Life"
|
||||
"Stay Calm"
|
||||
"Think Positive"
|
||||
"Be Happy"
|
||||
"No Fear"
|
||||
"Have Faith"
|
||||
"Trust Yourself"
|
||||
"Focus Now"
|
||||
"Take Action"
|
||||
"Never Settle"
|
||||
"Rise Up"
|
||||
"Shine On"
|
||||
"Stand Tall"
|
||||
"Live Free"
|
||||
"Just Begin"
|
||||
"Create Joy"
|
||||
"Stay Strong"
|
||||
"Breathe Deep"
|
||||
"Be Bold"
|
||||
"Look Ahead"
|
||||
"Move Forward"
|
||||
"Aim High"
|
||||
"Stay Humble"
|
||||
"Find Peace"
|
||||
"Do Good"
|
||||
"Seek Truth"
|
||||
"Love More"
|
||||
"Be Yourself"
|
||||
"Let Go"
|
||||
"Keep Smiling"
|
||||
"Stay Wild"
|
||||
"Think Big"
|
||||
"Be Awesome"
|
||||
"Start Now"
|
||||
"Enjoy Today"
|
||||
"Choose Joy"
|
||||
"Dream On"
|
||||
"Fly High"
|
||||
"Stay Focused"
|
||||
"Be Fearless"
|
||||
"Don't Stop"
|
||||
"Make Waves"
|
||||
"Be Original"
|
||||
"Stay Curious"
|
||||
"Be grateful"
|
||||
"Keep pushing"
|
||||
"Stay sharp"
|
||||
"Why not?"
|
||||
"Be still"
|
||||
"Keep cool"
|
||||
"Think twice"
|
||||
"Be ready"
|
||||
"Stay gold"
|
||||
"Game on"
|
||||
"Level up"
|
||||
"Code on"
|
||||
"Git commit"
|
||||
"Hack on"
|
||||
)
|
||||
|
||||
cyberpunk=(
|
||||
"System: ONLINE"
|
||||
"Encryption: ACTIVE"
|
||||
"Access: GRANTED"
|
||||
"Uptime: OPTIMAL"
|
||||
"Link: ESTABLISHED"
|
||||
"Protocol: SECURE"
|
||||
"Daemon: WATCHING"
|
||||
"Netrunner: READY"
|
||||
"Signal: STRONG"
|
||||
"Proxy: ENGAGED"
|
||||
"Root: ACCESS"
|
||||
"Kernel: PANIC"
|
||||
)
|
||||
|
||||
yojijukugo=(
|
||||
"一期一会"
|
||||
"花鳥風月"
|
||||
"温故知新"
|
||||
"七転八起"
|
||||
"自業自得"
|
||||
"以心伝心"
|
||||
"羊頭狗肉"
|
||||
"諸行無常"
|
||||
)
|
||||
|
||||
habits=(
|
||||
"Check posture"
|
||||
"Drink water"
|
||||
"Shoulders down"
|
||||
"Eyes off screen"
|
||||
"Deep breath"
|
||||
"Stretch now"
|
||||
"Unclench jaw"
|
||||
"Touch grass"
|
||||
"Blink now"
|
||||
"Stand up"
|
||||
)
|
||||
|
||||
dev=(
|
||||
"It works locally"
|
||||
"Sudo please"
|
||||
"Flake locked"
|
||||
"Compiling..."
|
||||
"Git push force"
|
||||
"rm -rf /"
|
||||
":q! to exit"
|
||||
"Works on my machine"
|
||||
"Coffee needed"
|
||||
"Fixing bugs"
|
||||
"Hello World"
|
||||
"Null Pointer"
|
||||
"Segfault"
|
||||
)
|
||||
|
||||
# Combine all arrays
|
||||
combined=(
|
||||
"''${greetings[@]}"
|
||||
"''${inspirations[@]}"
|
||||
# "''${cyberpunk[@]}"
|
||||
"''${yojijukugo[@]}"
|
||||
"''${habits[@]}"
|
||||
"''${dev[@]}"
|
||||
)
|
||||
|
||||
idx=$((RANDOM % ''${#combined[@]}))
|
||||
greeting="''${combined[$idx]}"
|
||||
|
||||
echo "$current_pid" > "$pid_file"
|
||||
echo "$greeting" > "$cache_file"
|
||||
echo "$greeting"
|
||||
'';
|
||||
in {
|
||||
home.packages = [
|
||||
hakase-hyprlock-text-generator
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
{pkgs, ...}: let
|
||||
hakase-hyprlock-typewriter = pkgs.writeShellScriptBin "hakase-hyprlock-typewriter" ''
|
||||
text="$1"
|
||||
if [[ -z "$text" ]]; then
|
||||
echo "Usage: $(basename "$0") [text]"
|
||||
exit 1
|
||||
fi
|
||||
state_file="''${XDG_RUNTIME_DIR:-/tmp}/typewriter_pos"
|
||||
blink_file="''${XDG_RUNTIME_DIR:-/tmp}/typewriter_blink"
|
||||
pid_file="''${XDG_RUNTIME_DIR:-/tmp}/typewriter_pid"
|
||||
|
||||
current_pid=$(pgrep -x hyprlock | head -1)
|
||||
|
||||
if [[ -f $pid_file ]]; then
|
||||
old_pid=$(cat $pid_file)
|
||||
if [[ "''${old_pid}" != "''${current_pid}" ]]; then
|
||||
rm -f "$state_file" "$blink_file"
|
||||
fi
|
||||
fi
|
||||
echo "$current_pid" >"$pid_file"
|
||||
|
||||
if [[ ! -f $state_file ]]; then
|
||||
echo 0 >"$state_file"
|
||||
fi
|
||||
|
||||
if [[ ! -f $blink_file ]]; then
|
||||
echo 0 >"$blink_file"
|
||||
fi
|
||||
|
||||
len=''${#text}
|
||||
letter=$(cat "$state_file")
|
||||
blink=$(cat "$blink_file")
|
||||
|
||||
if [[ $letter -lt $len ]]; then
|
||||
letter=$((letter + 1))
|
||||
echo "$letter" >"$state_file"
|
||||
echo "''${text:0:$letter}_"
|
||||
else
|
||||
# Toggle every 4 calls (at 200ms update = ~800ms blink)
|
||||
if (((blink / 4) % 2 == 0)); then
|
||||
echo "''${text}_"
|
||||
else
|
||||
echo "''${text}<span alpha=\"1%\">_</span>"
|
||||
fi
|
||||
fi
|
||||
|
||||
blink=$((blink + 1))
|
||||
echo "$blink" >"$blink_file"
|
||||
'';
|
||||
hakase-test-hyprlock-typewriter = pkgs.writeShellScriptBin "hakase-test-hyprlock-typewriter" ''
|
||||
for i in {1..10}; do
|
||||
hakase-hyprlock-typewriter
|
||||
done
|
||||
'';
|
||||
in {
|
||||
home.packages = [
|
||||
hakase-hyprlock-typewriter
|
||||
hakase-test-hyprlock-typewriter
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
myConfig,
|
||||
...
|
||||
}: let
|
||||
# TODO: rewrite
|
||||
wallpaperDir = "${config.home.homeDirectory}/.config/nixos/assets/Wallpapers";
|
||||
defaultWallpaper = "${wallpaperDir}/${myConfig.hyprland.wallpaper}";
|
||||
cacheWallpaper = "${config.home.homeDirectory}/.cache/current_wallpaper";
|
||||
|
||||
switch-wallpaper = pkgs.writeShellScriptBin "hakase-wallpaper-switch" ''
|
||||
if [[ "$1" != "run" ]]; then
|
||||
if command -v ghostty &> /dev/null; then
|
||||
ghostty --class="org.hakase.switch-wallpaper" --title="Wallpaper Selector" -e bash -c "hakase-wallpaper-switch run || read -p 'Hit Enter to close...'"
|
||||
exit 0
|
||||
elif command -v kitty &> /dev/null; then
|
||||
kitty --class org.hakase.switch-wallpaper --title "Wallpaper Selector" -e bash -c "hakase-wallpaper-switch run || read -p 'Hit Enter to close...'"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
tmp_file=$(mktemp)
|
||||
target_dir="$HOME/Pictures/Wallpapers"
|
||||
if [ ! -d "$target_dir" ]; then
|
||||
target_dir="$HOME"
|
||||
fi
|
||||
|
||||
# Ensure we are in a terminal that supports yazi
|
||||
${pkgs.yazi}/bin/yazi "$target_dir" --chooser-file="$tmp_file"
|
||||
|
||||
if [ ! -f "$tmp_file" ]; then
|
||||
echo "No selection file created."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
WALLPAPER=$(cat "$tmp_file")
|
||||
rm -f "$tmp_file"
|
||||
|
||||
if [ -z "$WALLPAPER" ]; then
|
||||
echo "No wallpaper selected."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Persistence logic
|
||||
CACHE_FILE="$HOME/.cache/current_wallpaper"
|
||||
cp "$WALLPAPER" "$CACHE_FILE"
|
||||
|
||||
# Reload hyprpaper
|
||||
${pkgs.hyprland}/bin/hyprctl hyprpaper unload all
|
||||
${pkgs.hyprland}/bin/hyprctl hyprpaper preload "$CACHE_FILE"
|
||||
${pkgs.hyprland}/bin/hyprctl hyprpaper wallpaper ",$CACHE_FILE"
|
||||
|
||||
exec matugen image "$CACHE_FILE"
|
||||
'';
|
||||
in {
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
exec-once = [
|
||||
"uwsm app -- hyprpaper"
|
||||
];
|
||||
|
||||
bindd = [
|
||||
"SUPER CTRL, I, Switch Wallpaper, exec, hakase-wallpaper-switch"
|
||||
];
|
||||
|
||||
windowrulev2 = [
|
||||
# --- WALLPAPER PICKER ---
|
||||
"float, class:^(org\.hakase\.switch-wallpaper)$"
|
||||
"float, initialTitle:^(Wallpaper Selector)$"
|
||||
"center, class:^(org\.hakase\.switch-wallpaper)$"
|
||||
"center, initialTitle:^(Wallpaper Selector)$"
|
||||
"size 60% 60%, class:^(org\.hakase\.switch-wallpaper)$"
|
||||
"size 60% 60%, initialTitle:^(Wallpaper Selector)$"
|
||||
"dimaround, class:^(org\.hakase\.switch-wallpaper)$"
|
||||
"dimaround, initialTitle:^(Wallpaper Selector)$"
|
||||
];
|
||||
};
|
||||
|
||||
services.hyprpaper = {
|
||||
enable = true;
|
||||
settings = {
|
||||
preload = [cacheWallpaper];
|
||||
wallpaper = [
|
||||
",${cacheWallpaper}"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
home.packages = [
|
||||
switch-wallpaper
|
||||
];
|
||||
|
||||
home.activation.setupWallpaper = lib.hm.dag.entryAfter ["writeBoundary"] ''
|
||||
if [ ! -f "${cacheWallpaper}" ]; then
|
||||
mkdir -p "$(dirname "${cacheWallpaper}")"
|
||||
if [ -f "${defaultWallpaper}" ]; then
|
||||
cp "${defaultWallpaper}" "${cacheWallpaper}"
|
||||
else
|
||||
echo "Default wallpaper not found at ${defaultWallpaper}"
|
||||
touch "${cacheWallpaper}"
|
||||
fi
|
||||
fi
|
||||
'';
|
||||
|
||||
systemd.user.startServices = "sd-switch";
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
{pkgs, ...}: let
|
||||
# Max window size (leave room for waybar/hyprbars)
|
||||
maxW = 2800;
|
||||
maxH = 1100;
|
||||
|
||||
swayimg-wrapper = pkgs.writeShellScriptBin "swayimg-wrapper" ''
|
||||
if [ -z "$1" ]; then
|
||||
exec ${pkgs.swayimg}/bin/swayimg
|
||||
fi
|
||||
|
||||
# Get image dimensions
|
||||
dims=$(${pkgs.file}/bin/file -b "$1" | ${pkgs.gnugrep}/bin/grep -oP '\d+ ?x ?\d+' | head -1 | tr -d ' ')
|
||||
if [ -z "$dims" ]; then
|
||||
# Fallback if file doesn't report dimensions
|
||||
exec ${pkgs.swayimg}/bin/swayimg "$@"
|
||||
fi
|
||||
|
||||
imgW=$(echo "$dims" | cut -dx -f1)
|
||||
imgH=$(echo "$dims" | cut -dx -f2)
|
||||
|
||||
# Calculate scale to fit within max bounds while preserving aspect ratio
|
||||
scaleW=$(echo "scale=4; ${toString maxW} / $imgW" | ${pkgs.bc}/bin/bc)
|
||||
scaleH=$(echo "scale=4; ${toString maxH} / $imgH" | ${pkgs.bc}/bin/bc)
|
||||
|
||||
# Use the smaller scale factor
|
||||
if [ $(echo "$scaleW < $scaleH" | ${pkgs.bc}/bin/bc) -eq 1 ]; then
|
||||
scale=$scaleW
|
||||
else
|
||||
scale=$scaleH
|
||||
fi
|
||||
|
||||
# Only scale down, not up
|
||||
if [ $(echo "$scale >= 1" | ${pkgs.bc}/bin/bc) -eq 1 ]; then
|
||||
exec ${pkgs.swayimg}/bin/swayimg "$@"
|
||||
fi
|
||||
|
||||
# Calculate new size
|
||||
newW=$(echo "$imgW * $scale / 1" | ${pkgs.bc}/bin/bc)
|
||||
newH=$(echo "$imgH * $scale / 1" | ${pkgs.bc}/bin/bc)
|
||||
|
||||
exec ${pkgs.swayimg}/bin/swayimg --size="$newW,$newH" "$@"
|
||||
'';
|
||||
in {
|
||||
home.packages = [pkgs.swayimg swayimg-wrapper];
|
||||
|
||||
xdg.mimeApps = {
|
||||
enable = true;
|
||||
defaultApplications = {
|
||||
"image/png" = "swayimg-wrapper.desktop";
|
||||
"image/jpeg" = "swayimg-wrapper.desktop";
|
||||
"image/gif" = "swayimg-wrapper.desktop";
|
||||
"image/webp" = "swayimg-wrapper.desktop";
|
||||
"image/bmp" = "swayimg-wrapper.desktop";
|
||||
"image/svg+xml" = "swayimg-wrapper.desktop";
|
||||
"image/tiff" = "swayimg-wrapper.desktop";
|
||||
};
|
||||
};
|
||||
|
||||
xdg.desktopEntries.swayimg-wrapper = {
|
||||
name = "Swayimg";
|
||||
exec = "swayimg-wrapper %f";
|
||||
terminal = false;
|
||||
type = "Application";
|
||||
mimeType = ["image/png" "image/jpeg" "image/gif" "image/webp" "image/bmp" "image/svg+xml" "image/tiff"];
|
||||
};
|
||||
|
||||
# swayimg config
|
||||
xdg.configFile."swayimg/config".text = ''
|
||||
[viewer]
|
||||
scale = fit
|
||||
|
||||
[info]
|
||||
show = no
|
||||
'';
|
||||
|
||||
wayland.windowManager.hyprland.settings.windowrulev2 = [
|
||||
# --- IMAGE VIEWER (swayimg) ---
|
||||
"float, class:^(swayimg)$"
|
||||
"center, class:^(swayimg)$"
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
{pkgs, ...}: {
|
||||
services.jellyfin-mpv-shim = {
|
||||
enable = true;
|
||||
package = pkgs.jellyfin-mpv-shim;
|
||||
|
||||
mpvConfig = {
|
||||
osc = false;
|
||||
osd-bar = false;
|
||||
load-scripts = true;
|
||||
input-vo-keyboard = true;
|
||||
input-default-bindings = true;
|
||||
|
||||
# Automatic subtitle selection logic:
|
||||
# Prefer English subtitles
|
||||
slang = "eng,en";
|
||||
# Prefer Japanese/Non-English audio first (if that's what you usually watch)
|
||||
# or just ensure English subs are picked when audio isn't English.
|
||||
sub-auto = "fuzzy";
|
||||
sub-visibility = "yes";
|
||||
};
|
||||
|
||||
mpvBindings = {
|
||||
"j" = "cycle sub";
|
||||
"S-j" = "cycle sub rev";
|
||||
"v" = "cycle sub-visibility";
|
||||
};
|
||||
|
||||
settings = {
|
||||
use_mpv_config = false;
|
||||
enable_osc = false;
|
||||
menu_mouse = true;
|
||||
|
||||
# Shim specific auto-sub logic
|
||||
# "subs-fallback" is a known good setting for the shim to handle this
|
||||
subtitle_color = "#FFFFFFFF";
|
||||
subtitle_size = 100;
|
||||
|
||||
audio_output = "hdmi";
|
||||
auto_play = true;
|
||||
fullscreen = true;
|
||||
player_name = "hakase";
|
||||
remote_kbps = 100000;
|
||||
local_kbps = 1000000;
|
||||
};
|
||||
};
|
||||
|
||||
# Modern OSC + Quality scripts
|
||||
home.file.".config/jellyfin-mpv-shim/scripts/uosc" = {
|
||||
source = "${pkgs.mpvScripts.uosc}/share/mpv/scripts/uosc";
|
||||
};
|
||||
home.file.".config/jellyfin-mpv-shim/scripts/thumbfast.lua" = {
|
||||
source = "${pkgs.mpvScripts.thumbfast}/share/mpv/scripts/thumbfast.lua";
|
||||
};
|
||||
home.file.".config/jellyfin-mpv-shim/scripts/autocrop.lua" = {
|
||||
source = "${pkgs.mpvScripts.autocrop}/share/mpv/scripts/autocrop.lua";
|
||||
};
|
||||
|
||||
home.file.".config/jellyfin-mpv-shim/fonts" = {
|
||||
source = "${pkgs.mpvScripts.uosc}/share/fonts";
|
||||
recursive = true;
|
||||
};
|
||||
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
exec-once = [ "systemctl --user start jellyfin-mpv-shim" ];
|
||||
windowrulev2 = [
|
||||
# --- JELLYFIN MPV SHIM ---
|
||||
"float, class:^(jellyfin-mpv-shim)$"
|
||||
"center, class:^(jellyfin-mpv-shim)$"
|
||||
"size 70% 70%, class:^(jellyfin-mpv-shim)$"
|
||||
"opacity 1.0 override 1.0 override, class:^(jellyfin-mpv-shim)$"
|
||||
"idleinhibit focus, class:^(jellyfin-mpv-shim)$"
|
||||
"noblur, class:^(jellyfin-mpv-shim)$"
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{pkgs, ...}: {
|
||||
home.packages = with pkgs; [
|
||||
# FIXME: only dark mode works. use matugen
|
||||
jellyfin-tui
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{pkgs, ...}: {
|
||||
home.packages = with pkgs; [
|
||||
jellyfin-media-player
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{pkgs, ...}: {
|
||||
home.packages = with pkgs; [
|
||||
libreoffice-fresh
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}: {
|
||||
home.packages = with pkgs; [
|
||||
libnotify
|
||||
];
|
||||
|
||||
services.mako.enable = true;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
[config] # FIXME: ~/.config feels unreliable. Use config.home.homeDirectory instead.
|
||||
reload_on_change = true
|
||||
|
||||
[templates.ghostty]
|
||||
input_path = "~/.config/matugen/templates/ghostty"
|
||||
output_path = "~/.config/ghostty/themes/matugen"
|
||||
post_hook = "killall -SIGUSR2 .ghostty-wrappe"
|
||||
|
||||
[templates.hyprland]
|
||||
input_path = "~/.config/matugen/templates/hyprland"
|
||||
output_path = "~/.config/hypr/matugen.conf"
|
||||
post_hook = "hyprctl reload"
|
||||
|
||||
[templates.waybar]
|
||||
input_path = "~/.config/matugen/templates/waybar"
|
||||
output_path = "~/.config/waybar/matugen.css"
|
||||
post_hook = "killall -SIGUSR2 .waybar-wrapped"
|
||||
|
||||
[templates.starship]
|
||||
input_path = "~/.config/matugen/templates/starship"
|
||||
output_path = "~/.config/starship.toml"
|
||||
|
||||
[templates.walker]
|
||||
input_path = "~/.config/matugen/templates/walker"
|
||||
output_path = "~/.config/walker/themes/nixos/style.css"
|
||||
|
||||
[templates.zathura]
|
||||
input_path = "~/.config/matugen/templates/zathura"
|
||||
output_path = "~/.config/zathura/zathura-matugen"
|
||||
|
||||
[templates.pywalfox]
|
||||
input_path = '~/.config/matugen/templates/firefox'
|
||||
output_path = '~/.cache/wal/colors.json'
|
||||
post_hook = 'pywalfox update'
|
||||
|
||||
[templates.cava]
|
||||
input_path = "~/.config/matugen/templates/cava"
|
||||
output_path = "~/.config/cava/config"
|
||||
post_hook = "pkill -USR1 cava"
|
||||
|
||||
[templates.gtk3]
|
||||
input_path = "~/.config/matugen/templates/gtk3"
|
||||
output_path = "~/.config/gtk-3.0/colors.css"
|
||||
|
||||
[templates.gtk4]
|
||||
input_path = "~/.config/matugen/templates/gtk4"
|
||||
output_path = "~/.config/gtk-4.0/colors.css"
|
||||
|
||||
[templates.hyprlock]
|
||||
input_path = "~/.config/matugen/templates/hyprlock"
|
||||
output_path = "~/.config/hypr/hyprlock-colors.conf"
|
||||
|
||||
[templates.mako]
|
||||
input_path = "~/.config/matugen/templates/mako"
|
||||
output_path = "~/.config/mako/config"
|
||||
post_hook = "makoctl reload"
|
||||
|
||||
[templates.vicinae]
|
||||
input_path = "~/.config/matugen/templates/vicinae"
|
||||
output_path = "~/.local/share/vicinae/themes/matugen.toml"
|
||||
post_hook = "vicinae theme set matugen"
|
||||
|
||||
[templates.theme-switch]
|
||||
input_path = "~/.config/matugen/templates/theme-switch"
|
||||
output_path = "~/.config/matugen/scripts/theme-switch.sh"
|
||||
post_hook = "sh ~/.config/matugen/scripts/theme-switch.sh"
|
||||
@@ -0,0 +1,395 @@
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
myConfig,
|
||||
...
|
||||
}: {
|
||||
home.packages = with pkgs; [
|
||||
matugen
|
||||
dconf
|
||||
psmisc # for killall
|
||||
];
|
||||
home.file.".config/matugen/config.toml" = {
|
||||
source = ./config.toml;
|
||||
};
|
||||
|
||||
# Copy static templates
|
||||
home.file.".config/matugen/templates/theme-switch".text = ''
|
||||
#!/bin/sh
|
||||
# Generated by Matugen
|
||||
|
||||
# mode will be replaced by 'dark' or 'light'
|
||||
MODE="{{mode}}"
|
||||
|
||||
if [ "$MODE" = "dark" ]; then
|
||||
${pkgs.dconf}/bin/dconf write /org/gnome/desktop/interface/color-scheme "'prefer-dark'"
|
||||
else
|
||||
${pkgs.dconf}/bin/dconf write /org/gnome/desktop/interface/color-scheme "'prefer-light'"
|
||||
fi
|
||||
'';
|
||||
home.file.".config/matugen/templates/cava".source = ./templates/cava;
|
||||
home.file.".config/matugen/templates/firefox".source = ./templates/firefox;
|
||||
home.file.".config/matugen/templates/ghostty".source = ./templates/ghostty;
|
||||
home.file.".config/matugen/templates/gtk3".source = ./templates/gtk3;
|
||||
home.file.".config/matugen/templates/gtk4".source = ./templates/gtk4;
|
||||
home.file.".config/matugen/templates/hyprland".source = ./templates/hyprland;
|
||||
home.file.".config/matugen/templates/hyprlock".source = ./templates/hyprlock;
|
||||
home.file.".config/matugen/templates/starship".source = ./templates/starship;
|
||||
home.file.".config/matugen/templates/waybar".source = ./templates/waybar;
|
||||
home.file.".config/matugen/templates/zathura".source = ./templates/zathura;
|
||||
|
||||
home.file.".config/matugen/templates/vicinae".text = ''
|
||||
# Vicinae Matugen Theme Template
|
||||
|
||||
[meta]
|
||||
name = "Matugen"
|
||||
description = "Material You theme generated by Matugen - {{mode}} variant"
|
||||
variant = "{{mode}}"
|
||||
|
||||
# ============================================================================
|
||||
# Typography
|
||||
# ============================================================================
|
||||
|
||||
[typography]
|
||||
font_family = "${myConfig.font.monospace}"
|
||||
|
||||
# ============================================================================
|
||||
# Core Colors
|
||||
# ============================================================================
|
||||
|
||||
[colors.core]
|
||||
accent = "{{colors.primary.default.hex}}"
|
||||
accent_foreground = "{{colors.on_primary.default.hex}}"
|
||||
background = "{{colors.surface.default.hex}}"
|
||||
foreground = "{{colors.on_surface.default.hex}}"
|
||||
secondary_background = "{{colors.surface_container.default.hex}}"
|
||||
border = "{{colors.outline_variant.default.hex}}"
|
||||
|
||||
# ============================================================================
|
||||
# Window Borders
|
||||
# ============================================================================
|
||||
|
||||
[colors.main_window]
|
||||
border = "{{colors.outline_variant.default.hex}}"
|
||||
|
||||
[colors.settings_window]
|
||||
border = "{{colors.outline.default.hex}}"
|
||||
|
||||
# ============================================================================
|
||||
# Accent Palette
|
||||
# ============================================================================
|
||||
|
||||
[colors.accents]
|
||||
blue = "{{colors.primary.default.hex}}"
|
||||
green = "{{colors.tertiary.default.hex}}"
|
||||
magenta = "{{colors.secondary.default.hex}}"
|
||||
orange = { name = "{{colors.error.default.hex}}", lighter = 40 }
|
||||
red = "{{colors.error.default.hex}}"
|
||||
yellow = { name = "{{colors.tertiary.default.hex}}", lighter = 80 }
|
||||
cyan = { name = "{{colors.primary.default.hex}}", lighter = 50 }
|
||||
purple = "{{colors.secondary.default.hex}}"
|
||||
|
||||
# ============================================================================
|
||||
# Text System
|
||||
# ============================================================================
|
||||
|
||||
[colors.text]
|
||||
default = "{{colors.on_surface.default.hex}}"
|
||||
muted = "{{colors.on_surface_variant.default.hex}}"
|
||||
danger = "{{colors.error.default.hex}}"
|
||||
success = "{{colors.tertiary.default.hex}}"
|
||||
placeholder = { name = "{{colors.on_surface_variant.default.hex}}", opacity = 0.6 }
|
||||
|
||||
[colors.text.selection]
|
||||
background = "{{colors.primary.default.hex}}"
|
||||
foreground = "{{colors.on_primary.default.hex}}"
|
||||
|
||||
[colors.text.links]
|
||||
default = "{{colors.primary.default.hex}}"
|
||||
visited = { name = "{{colors.tertiary.default.hex}}", darker = 20 }
|
||||
|
||||
# ============================================================================
|
||||
# Input Fields
|
||||
# ============================================================================
|
||||
|
||||
[colors.input]
|
||||
border = "{{colors.outline.default.hex}}"
|
||||
border_focus = "{{colors.primary.default.hex}}"
|
||||
border_error = "{{colors.error.default.hex}}"
|
||||
|
||||
# ============================================================================
|
||||
# Buttons
|
||||
# ============================================================================
|
||||
|
||||
[colors.button.primary]
|
||||
background = "{{colors.surface_container_high.default.hex}}"
|
||||
foreground = "{{colors.on_surface.default.hex}}"
|
||||
|
||||
[colors.button.primary.hover]
|
||||
background = "{{colors.surface_container_highest.default.hex}}"
|
||||
|
||||
[colors.button.primary.focus]
|
||||
outline = "{{colors.primary.default.hex}}"
|
||||
|
||||
# ============================================================================
|
||||
# Lists
|
||||
# ============================================================================
|
||||
|
||||
[colors.list.item.hover]
|
||||
background = { name = "{{colors.primary_container.default.hex}}", opacity = 0.25 }
|
||||
foreground = "{{colors.on_surface.default.hex}}"
|
||||
|
||||
[colors.list.item.selection]
|
||||
background = { name = "{{colors.primary_container.default.hex}}", opacity = 0.50 }
|
||||
foreground = "{{colors.on_primary_container.default.hex}}"
|
||||
secondary_background = "{{colors.primary_container.default.hex}}"
|
||||
secondary_foreground = "{{colors.on_primary_container.default.hex}}"
|
||||
|
||||
# ============================================================================
|
||||
# Grid Items
|
||||
# ============================================================================
|
||||
|
||||
[colors.grid.item]
|
||||
background = "{{colors.surface_container.default.hex}}"
|
||||
|
||||
[colors.grid.item.hover]
|
||||
outline = { name = "{{colors.secondary.default.hex}}", opacity = 0.8 }
|
||||
|
||||
[colors.grid.item.selection]
|
||||
outline = { name = "{{colors.primary.default.hex}}" }
|
||||
|
||||
# ============================================================================
|
||||
# Scrollbars
|
||||
# ============================================================================
|
||||
|
||||
[colors.scrollbars]
|
||||
background = { name = "{{colors.primary.default.hex}}", opacity = 0.2 }
|
||||
|
||||
# ============================================================================
|
||||
# Loading States
|
||||
# ============================================================================
|
||||
|
||||
[colors.loading]
|
||||
bar = "{{colors.primary.default.hex}}"
|
||||
spinner = "{{colors.primary.default.hex}}"
|
||||
'';
|
||||
|
||||
# Generate templates with font interpolation
|
||||
home.file.".config/matugen/templates/walker".text = ''
|
||||
/* @import "../../../../../../../.config/omarchy/current/theme/walker.css"; */
|
||||
|
||||
/* Define Matugen Colors */
|
||||
@define-color text {{colors.on_surface.default.hex}};
|
||||
@define-color base {{colors.surface_container.default.hex}};
|
||||
@define-color border {{colors.primary.default.hex}};
|
||||
@define-color selected_text {{colors.primary.default.hex}};
|
||||
@define-color background {{colors.surface.default.hex}};
|
||||
|
||||
* {
|
||||
all: unset;
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: ${myConfig.font.monospace};
|
||||
font-size: 18px;
|
||||
color: @text;
|
||||
}
|
||||
|
||||
scrollbar {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.normal-icons {
|
||||
-gtk-icon-size: 16px;
|
||||
}
|
||||
|
||||
.large-icons {
|
||||
-gtk-icon-size: 32px;
|
||||
}
|
||||
|
||||
.box-wrapper {
|
||||
background: alpha(@base, 0.95);
|
||||
padding: 20px;
|
||||
border: 2px solid @border;
|
||||
}
|
||||
|
||||
.preview-box {
|
||||
}
|
||||
|
||||
.box {
|
||||
}
|
||||
|
||||
.search-container {
|
||||
background: @base;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.input placeholder {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.input {
|
||||
}
|
||||
|
||||
.input:focus,
|
||||
.input:active {
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.content-container {
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
}
|
||||
|
||||
.scroll {
|
||||
}
|
||||
|
||||
.list {
|
||||
}
|
||||
|
||||
child,
|
||||
child > * {
|
||||
}
|
||||
|
||||
child:hover .item-box {
|
||||
}
|
||||
|
||||
child:selected .item-box {
|
||||
}
|
||||
|
||||
child:selected .item-box * {
|
||||
color: @selected_text;
|
||||
}
|
||||
|
||||
.item-box {
|
||||
padding-left: 14px;
|
||||
}
|
||||
|
||||
.item-text-box {
|
||||
all: unset;
|
||||
padding: 14px 0;
|
||||
}
|
||||
|
||||
.item-text {
|
||||
}
|
||||
|
||||
.item-subtext {
|
||||
font-size: 0px;
|
||||
min-height: 0px;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.item-image {
|
||||
margin-right: 14px;
|
||||
-gtk-icon-transform: scale(0.9);
|
||||
}
|
||||
|
||||
.current {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.keybind-hints {
|
||||
background: @background;
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.preview {
|
||||
}
|
||||
'';
|
||||
|
||||
home.file.".config/matugen/templates/mako".text = ''
|
||||
# Mako notification daemon configuration
|
||||
# Generated by matugen
|
||||
|
||||
# Appearance
|
||||
font=${myConfig.font.sans} 11
|
||||
width=350
|
||||
height=150
|
||||
margin=10
|
||||
padding=15
|
||||
border-size=2
|
||||
border-radius=8
|
||||
|
||||
# Behavior
|
||||
default-timeout=5000
|
||||
ignore-timeout=false
|
||||
layer=overlay
|
||||
anchor=top-right
|
||||
|
||||
# Interaction
|
||||
markup=true
|
||||
actions=true
|
||||
|
||||
# Grouping
|
||||
group-by=app-name
|
||||
max-visible=5
|
||||
sort=-time
|
||||
|
||||
# Theme colors from matugen
|
||||
background-color=#{{colors.surface_container_high.default.hex_stripped}}
|
||||
text-color=#{{colors.on_surface.default.hex_stripped}}
|
||||
border-color=#{{colors.primary.default.hex_stripped}}
|
||||
progress-color=over #{{colors.primary_container.default.hex_stripped}}
|
||||
|
||||
[urgency=low]
|
||||
border-color=#{{colors.tertiary.default.hex_stripped}}
|
||||
|
||||
[urgency=normal]
|
||||
border-color=#{{colors.primary.default.hex_stripped}}
|
||||
|
||||
[urgency=high]
|
||||
border-color=#{{colors.error.default.hex_stripped}}
|
||||
default-timeout=0
|
||||
'';
|
||||
|
||||
# Qt theming - follow GTK theme
|
||||
qt = {
|
||||
enable = true;
|
||||
platformTheme.name = "gtk";
|
||||
};
|
||||
|
||||
dconf.settings = {
|
||||
"org/gnome/desktop/interface" = {
|
||||
color-scheme =
|
||||
if myConfig.theme.mode == "dark"
|
||||
then "prefer-dark"
|
||||
else "prefer-light";
|
||||
};
|
||||
};
|
||||
|
||||
# GTK theming with adw-gtk3 and Matugen colors
|
||||
gtk = {
|
||||
enable = true;
|
||||
theme = {
|
||||
name = "adw-gtk3";
|
||||
package = pkgs.adw-gtk3;
|
||||
};
|
||||
iconTheme = {
|
||||
name = "Papirus-Dark";
|
||||
package = pkgs.papirus-icon-theme;
|
||||
};
|
||||
gtk3.extraCss = ''@import url("colors.css");'';
|
||||
gtk3.extraConfig = {
|
||||
gtk-application-prefer-dark-theme =
|
||||
if myConfig.theme.mode == "dark"
|
||||
then 1
|
||||
else 0;
|
||||
};
|
||||
gtk4.extraCss = ''@import url("colors.css");'';
|
||||
gtk4.extraConfig = {
|
||||
gtk-application-prefer-dark-theme =
|
||||
if myConfig.theme.mode == "dark"
|
||||
then 1
|
||||
else 0;
|
||||
};
|
||||
};
|
||||
|
||||
programs.ghostty.settings.theme = "matugen";
|
||||
programs.starship.enable = true;
|
||||
wayland.windowManager.hyprland.settings.source = ["./matugen.conf"];
|
||||
programs.walker.config.theme = "nixos";
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
[general]
|
||||
framerate = 60
|
||||
autosens = 1
|
||||
bars = 0
|
||||
bar_width = 3
|
||||
bar_spacing = 1
|
||||
sleep_timer = 5
|
||||
|
||||
[input]
|
||||
method = pipewire
|
||||
source = auto
|
||||
|
||||
[output]
|
||||
method = ncurses
|
||||
style = stereo
|
||||
|
||||
[color]
|
||||
gradient = 1
|
||||
gradient_count = 6
|
||||
gradient_color_1 = '{{colors.primary.default.hex}}'
|
||||
gradient_color_2 = '{{colors.primary_container.default.hex}}'
|
||||
gradient_color_3 = '{{colors.secondary.default.hex}}'
|
||||
gradient_color_4 = '{{colors.secondary_container.default.hex}}'
|
||||
gradient_color_5 = '{{colors.tertiary.default.hex}}'
|
||||
gradient_color_6 = '{{colors.tertiary_container.default.hex}}'
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"wallpaper": "{{image}}",
|
||||
"alpha": "100",
|
||||
"colors": {
|
||||
"color0": "{{colors.background.default.hex}}",
|
||||
"color1": "",
|
||||
"color2": "",
|
||||
"color3": "",
|
||||
"color4": "",
|
||||
"color5": "",
|
||||
"color6": "",
|
||||
"color7": "",
|
||||
"color8": "",
|
||||
"color9": "",
|
||||
"color10": "{{colors.primary.default.hex}}",
|
||||
"color11": "",
|
||||
"color12": "",
|
||||
"color13": "{{colors.surface_bright.default.hex}}",
|
||||
"color14": "",
|
||||
"color15": "{{colors.on_surface.default.hex}}"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
background = {{colors.background.default.hex}}
|
||||
foreground = {{colors.on_surface.default.hex}}
|
||||
cursor-color = {{colors.on_surface.default.hex}}
|
||||
cursor-text = {{colors.on_surface_variant.default.hex}}
|
||||
selection-background = {{colors.secondary_fixed_dim.default.hex}}
|
||||
selection-foreground = {{colors.on_secondary.default.hex}}
|
||||
@@ -0,0 +1,94 @@
|
||||
@define-color accent_color {{colors.primary.default.hex}};
|
||||
@define-color accent_bg_color {{colors.primary.default.hex}};
|
||||
@define-color accent_fg_color {{colors.on_primary.default.hex}};
|
||||
@define-color destructive_color {{colors.error.default.hex}};
|
||||
@define-color destructive_bg_color {{colors.error.default.hex}};
|
||||
@define-color destructive_fg_color {{colors.on_error.default.hex}};
|
||||
@define-color success_color {{colors.tertiary.default.hex}};
|
||||
@define-color success_bg_color {{colors.tertiary.default.hex}};
|
||||
@define-color success_fg_color {{colors.on_tertiary.default.hex}};
|
||||
@define-color warning_color {{colors.secondary.default.hex}};
|
||||
@define-color warning_bg_color {{colors.secondary.default.hex}};
|
||||
@define-color warning_fg_color {{colors.on_secondary.default.hex}};
|
||||
@define-color error_color {{colors.error.default.hex}};
|
||||
@define-color error_bg_color {{colors.error.default.hex}};
|
||||
@define-color error_fg_color {{colors.on_error.default.hex}};
|
||||
@define-color window_bg_color {{colors.surface.default.hex}};
|
||||
@define-color window_fg_color {{colors.on_surface.default.hex}};
|
||||
@define-color view_bg_color {{colors.surface_container.default.hex}};
|
||||
@define-color view_fg_color {{colors.on_surface.default.hex}};
|
||||
@define-color headerbar_bg_color {{colors.surface_container.default.hex}};
|
||||
@define-color headerbar_fg_color {{colors.on_surface.default.hex}};
|
||||
@define-color headerbar_border_color transparent;
|
||||
@define-color headerbar_backdrop_color {{colors.surface.default.hex}};
|
||||
@define-color headerbar_shade_color rgba(0, 0, 0, 0.07);
|
||||
@define-color card_bg_color {{colors.surface_container_low.default.hex}};
|
||||
@define-color card_fg_color {{colors.on_surface.default.hex}};
|
||||
@define-color card_shade_color rgba(0, 0, 0, 0.07);
|
||||
@define-color dialog_bg_color {{colors.surface_container_high.default.hex}};
|
||||
@define-color dialog_fg_color {{colors.on_surface.default.hex}};
|
||||
@define-color popover_bg_color {{colors.surface_container.default.hex}};
|
||||
@define-color popover_fg_color {{colors.on_surface.default.hex}};
|
||||
@define-color shade_color rgba(0, 0, 0, 0.07);
|
||||
@define-color scrollbar_outline_color rgba(0, 0, 0, 0.5);
|
||||
@define-color blue_1 {{colors.primary.default.hex}};
|
||||
@define-color blue_2 {{colors.primary.default.hex}};
|
||||
@define-color blue_3 {{colors.primary.default.hex}};
|
||||
@define-color blue_4 {{colors.primary.default.hex}};
|
||||
@define-color blue_5 {{colors.primary.default.hex}};
|
||||
@define-color green_1 {{colors.tertiary.default.hex}};
|
||||
@define-color green_2 {{colors.tertiary.default.hex}};
|
||||
@define-color green_3 {{colors.tertiary.default.hex}};
|
||||
@define-color green_4 {{colors.tertiary.default.hex}};
|
||||
@define-color green_5 {{colors.tertiary.default.hex}};
|
||||
@define-color yellow_1 {{colors.secondary.default.hex}};
|
||||
@define-color yellow_2 {{colors.secondary.default.hex}};
|
||||
@define-color yellow_3 {{colors.secondary.default.hex}};
|
||||
@define-color yellow_4 {{colors.secondary.default.hex}};
|
||||
@define-color yellow_5 {{colors.secondary.default.hex}};
|
||||
@define-color orange_1 {{colors.secondary.default.hex}};
|
||||
@define-color orange_2 {{colors.secondary.default.hex}};
|
||||
@define-color orange_3 {{colors.secondary.default.hex}};
|
||||
@define-color orange_4 {{colors.secondary.default.hex}};
|
||||
@define-color orange_5 {{colors.secondary.default.hex}};
|
||||
@define-color red_1 {{colors.error.default.hex}};
|
||||
@define-color red_2 {{colors.error.default.hex}};
|
||||
@define-color red_3 {{colors.error.default.hex}};
|
||||
@define-color red_4 {{colors.error.default.hex}};
|
||||
@define-color red_5 {{colors.error.default.hex}};
|
||||
@define-color purple_1 {{colors.tertiary.default.hex}};
|
||||
@define-color purple_2 {{colors.tertiary.default.hex}};
|
||||
@define-color purple_3 {{colors.tertiary.default.hex}};
|
||||
@define-color purple_4 {{colors.tertiary.default.hex}};
|
||||
@define-color purple_5 {{colors.tertiary.default.hex}};
|
||||
@define-color brown_1 {{colors.surface_variant.default.hex}};
|
||||
@define-color brown_2 {{colors.surface_variant.default.hex}};
|
||||
@define-color brown_3 {{colors.surface_variant.default.hex}};
|
||||
@define-color brown_4 {{colors.surface_variant.default.hex}};
|
||||
@define-color brown_5 {{colors.surface_variant.default.hex}};
|
||||
@define-color light_1 {{colors.surface_bright.default.hex}};
|
||||
@define-color light_2 {{colors.surface.default.hex}};
|
||||
@define-color light_3 {{colors.surface_dim.default.hex}};
|
||||
@define-color light_4 {{colors.surface_container.default.hex}};
|
||||
@define-color light_5 {{colors.surface_container_high.default.hex}};
|
||||
@define-color dark_1 {{colors.surface_dim.default.hex}};
|
||||
@define-color dark_2 {{colors.surface.default.hex}};
|
||||
@define-color dark_3 {{colors.surface_container.default.hex}};
|
||||
@define-color dark_4 {{colors.surface_container_high.default.hex}};
|
||||
@define-color dark_5 {{colors.surface_container_highest.default.hex}};
|
||||
|
||||
/* Sidebar Fixes */
|
||||
.sidebar, .navigation-sidebar {
|
||||
background-color: @view_bg_color;
|
||||
color: @view_fg_color;
|
||||
}
|
||||
|
||||
.sidebar list, .navigation-sidebar list {
|
||||
background-color: transparent;
|
||||
color: @view_fg_color;
|
||||
}
|
||||
|
||||
filechooser .sidebar {
|
||||
background-color: @view_bg_color;
|
||||
color: @view_fg_color;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
@define-color accent_color {{colors.primary.default.hex}};
|
||||
@define-color accent_bg_color {{colors.primary.default.hex}};
|
||||
@define-color accent_fg_color {{colors.on_primary.default.hex}};
|
||||
@define-color destructive_color {{colors.error.default.hex}};
|
||||
@define-color destructive_bg_color {{colors.error.default.hex}};
|
||||
@define-color destructive_fg_color {{colors.on_error.default.hex}};
|
||||
@define-color success_color {{colors.tertiary.default.hex}};
|
||||
@define-color success_bg_color {{colors.tertiary.default.hex}};
|
||||
@define-color success_fg_color {{colors.on_tertiary.default.hex}};
|
||||
@define-color warning_color {{colors.secondary.default.hex}};
|
||||
@define-color warning_bg_color {{colors.secondary.default.hex}};
|
||||
@define-color warning_fg_color {{colors.on_secondary.default.hex}};
|
||||
@define-color error_color {{colors.error.default.hex}};
|
||||
@define-color error_bg_color {{colors.error.default.hex}};
|
||||
@define-color error_fg_color {{colors.on_error.default.hex}};
|
||||
@define-color window_bg_color {{colors.surface.default.hex}};
|
||||
@define-color window_fg_color {{colors.on_surface.default.hex}};
|
||||
@define-color view_bg_color {{colors.surface_container.default.hex}};
|
||||
@define-color view_fg_color {{colors.on_surface.default.hex}};
|
||||
@define-color headerbar_bg_color {{colors.surface_container.default.hex}};
|
||||
@define-color headerbar_fg_color {{colors.on_surface.default.hex}};
|
||||
@define-color headerbar_border_color transparent;
|
||||
@define-color headerbar_backdrop_color {{colors.surface.default.hex}};
|
||||
@define-color headerbar_shade_color rgba(0, 0, 0, 0.07);
|
||||
@define-color card_bg_color {{colors.surface_container_low.default.hex}};
|
||||
@define-color card_fg_color {{colors.on_surface.default.hex}};
|
||||
@define-color card_shade_color rgba(0, 0, 0, 0.07);
|
||||
@define-color dialog_bg_color {{colors.surface_container_high.default.hex}};
|
||||
@define-color dialog_fg_color {{colors.on_surface.default.hex}};
|
||||
@define-color popover_bg_color {{colors.surface_container.default.hex}};
|
||||
@define-color popover_fg_color {{colors.on_surface.default.hex}};
|
||||
@define-color shade_color rgba(0, 0, 0, 0.07);
|
||||
@define-color scrollbar_outline_color rgba(0, 0, 0, 0.5);
|
||||
@define-color blue_1 {{colors.primary.default.hex}};
|
||||
@define-color blue_2 {{colors.primary.default.hex}};
|
||||
@define-color blue_3 {{colors.primary.default.hex}};
|
||||
@define-color blue_4 {{colors.primary.default.hex}};
|
||||
@define-color blue_5 {{colors.primary.default.hex}};
|
||||
@define-color green_1 {{colors.tertiary.default.hex}};
|
||||
@define-color green_2 {{colors.tertiary.default.hex}};
|
||||
@define-color green_3 {{colors.tertiary.default.hex}};
|
||||
@define-color green_4 {{colors.tertiary.default.hex}};
|
||||
@define-color green_5 {{colors.tertiary.default.hex}};
|
||||
@define-color yellow_1 {{colors.secondary.default.hex}};
|
||||
@define-color yellow_2 {{colors.secondary.default.hex}};
|
||||
@define-color yellow_3 {{colors.secondary.default.hex}};
|
||||
@define-color yellow_4 {{colors.secondary.default.hex}};
|
||||
@define-color yellow_5 {{colors.secondary.default.hex}};
|
||||
@define-color orange_1 {{colors.secondary.default.hex}};
|
||||
@define-color orange_2 {{colors.secondary.default.hex}};
|
||||
@define-color orange_3 {{colors.secondary.default.hex}};
|
||||
@define-color orange_4 {{colors.secondary.default.hex}};
|
||||
@define-color orange_5 {{colors.secondary.default.hex}};
|
||||
@define-color red_1 {{colors.error.default.hex}};
|
||||
@define-color red_2 {{colors.error.default.hex}};
|
||||
@define-color red_3 {{colors.error.default.hex}};
|
||||
@define-color red_4 {{colors.error.default.hex}};
|
||||
@define-color red_5 {{colors.error.default.hex}};
|
||||
@define-color purple_1 {{colors.tertiary.default.hex}};
|
||||
@define-color purple_2 {{colors.tertiary.default.hex}};
|
||||
@define-color purple_3 {{colors.tertiary.default.hex}};
|
||||
@define-color purple_4 {{colors.tertiary.default.hex}};
|
||||
@define-color purple_5 {{colors.tertiary.default.hex}};
|
||||
@define-color brown_1 {{colors.surface_variant.default.hex}};
|
||||
@define-color brown_2 {{colors.surface_variant.default.hex}};
|
||||
@define-color brown_3 {{colors.surface_variant.default.hex}};
|
||||
@define-color brown_4 {{colors.surface_variant.default.hex}};
|
||||
@define-color brown_5 {{colors.surface_variant.default.hex}};
|
||||
@define-color light_1 {{colors.surface_bright.default.hex}};
|
||||
@define-color light_2 {{colors.surface.default.hex}};
|
||||
@define-color light_3 {{colors.surface_dim.default.hex}};
|
||||
@define-color light_4 {{colors.surface_container.default.hex}};
|
||||
@define-color light_5 {{colors.surface_container_high.default.hex}};
|
||||
@define-color dark_1 {{colors.surface_dim.default.hex}};
|
||||
@define-color dark_2 {{colors.surface.default.hex}};
|
||||
@define-color dark_3 {{colors.surface_container.default.hex}};
|
||||
@define-color dark_4 {{colors.surface_container_high.default.hex}};
|
||||
@define-color dark_5 {{colors.surface_container_highest.default.hex}};
|
||||
|
||||
/* Sidebar Fixes */
|
||||
.sidebar, .navigation-sidebar {
|
||||
background-color: @view_bg_color;
|
||||
color: @view_fg_color;
|
||||
}
|
||||
|
||||
.sidebar list, .navigation-sidebar list {
|
||||
background-color: transparent;
|
||||
color: @view_fg_color;
|
||||
}
|
||||
|
||||
filechooser .sidebar {
|
||||
background-color: @view_bg_color;
|
||||
color: @view_fg_color;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<* for name, value in colors *>
|
||||
$image = {{image}}
|
||||
${{name}} = rgba({{value.default.hex_stripped}}ff)
|
||||
<* endfor *>
|
||||
@@ -0,0 +1,4 @@
|
||||
$image = {{image}}
|
||||
<* for name, value in colors *>
|
||||
${{name}} = rgba({{value.default.hex_stripped}}ff)
|
||||
<* endfor *>
|
||||
@@ -0,0 +1,42 @@
|
||||
# Mako notification daemon configuration
|
||||
# Generated by matugen
|
||||
|
||||
# Appearance
|
||||
font=Sans 11
|
||||
width=350
|
||||
height=150
|
||||
margin=10
|
||||
padding=15
|
||||
border-size=2
|
||||
border-radius=8
|
||||
|
||||
# Behavior
|
||||
default-timeout=5000
|
||||
ignore-timeout=false
|
||||
layer=overlay
|
||||
anchor=top-right
|
||||
|
||||
# Interaction
|
||||
markup=true
|
||||
actions=true
|
||||
|
||||
# Grouping
|
||||
group-by=app-name
|
||||
max-visible=5
|
||||
sort=-time
|
||||
|
||||
# Theme colors from matugen
|
||||
background-color=#{{colors.surface_container_high.default.hex_stripped}}
|
||||
text-color=#{{colors.on_surface.default.hex_stripped}}
|
||||
border-color=#{{colors.primary.default.hex_stripped}}
|
||||
progress-color=over #{{colors.primary_container.default.hex_stripped}}
|
||||
|
||||
[urgency=low]
|
||||
border-color=#{{colors.tertiary.default.hex_stripped}}
|
||||
|
||||
[urgency=normal]
|
||||
border-color=#{{colors.primary.default.hex_stripped}}
|
||||
|
||||
[urgency=high]
|
||||
border-color=#{{colors.error.default.hex_stripped}}
|
||||
default-timeout=0
|
||||
@@ -0,0 +1,53 @@
|
||||
format = '''
|
||||
[╭─](color1)$username$hostname$directory$git_branch$git_state$git_status$cmd_duration$line_break[╰─](color1)$python$character'''
|
||||
|
||||
palette = 'colors'
|
||||
|
||||
[palettes.colors]
|
||||
mustard = '#af8700' # example
|
||||
color1 = '{{colors.primary_fixed_dim.default.hex}}'
|
||||
color2 = '{{colors.on_primary.default.hex}}'
|
||||
color3 = '{{colors.on_surface_variant.default.hex}}'
|
||||
color4 = '{{colors.surface_container.default.hex}}'
|
||||
color5 = '{{colors.on_primary.default.hex}}'
|
||||
color6 = '{{colors.surface_dim.default.hex}}'
|
||||
color7 = '{{colors.surface.default.hex}}'
|
||||
color8 = '{{colors.primary.default.hex}}'
|
||||
color9 = '{{colors.tertiary.default.hex}}'
|
||||
|
||||
[directory]
|
||||
style = "bold color8"
|
||||
|
||||
[character]
|
||||
success_symbol = "[❯](bold color9)"
|
||||
error_symbol = "[❯](bold red)"
|
||||
vicmd_symbol = "[❮](bold color3)"
|
||||
|
||||
[git_branch]
|
||||
format = "[$branch]($style) "
|
||||
style = "bold color3"
|
||||
|
||||
[git_status]
|
||||
format = "[[(*$conflicted$untracked$modified$staged$renamed$deleted)](color9) ($ahead_behind$stashed)]($style) "
|
||||
style = "bold color9"
|
||||
conflicted = ""
|
||||
untracked = ""
|
||||
modified = ""
|
||||
staged = ""
|
||||
renamed = ""
|
||||
deleted = ""
|
||||
stashed = "≡"
|
||||
|
||||
[git_state]
|
||||
format = '\([$state( $progress_current/$progress_total)]($style)\) '
|
||||
style = "bold color3"
|
||||
|
||||
[cmd_duration]
|
||||
format = "[$duration]($style) "
|
||||
style = "bold mustard"
|
||||
|
||||
[python]
|
||||
format = "[$virtualenv]($style) "
|
||||
style = "bold color3"
|
||||
detect_extensions = []
|
||||
detect_files = []
|
||||
@@ -0,0 +1,123 @@
|
||||
/* @import "../../../../../../../.config/omarchy/current/theme/walker.css"; */
|
||||
|
||||
/* Define Matugen Colors */
|
||||
@define-color text {{colors.on_surface.default.hex}};
|
||||
@define-color base {{colors.surface_container.default.hex}};
|
||||
@define-color border {{colors.primary.default.hex}};
|
||||
@define-color selected_text {{colors.primary.default.hex}};
|
||||
@define-color background {{colors.surface.default.hex}};
|
||||
|
||||
* {
|
||||
all: unset;
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: monospace;
|
||||
font-size: 18px;
|
||||
color: @text;
|
||||
}
|
||||
|
||||
scrollbar {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.normal-icons {
|
||||
-gtk-icon-size: 16px;
|
||||
}
|
||||
|
||||
.large-icons {
|
||||
-gtk-icon-size: 32px;
|
||||
}
|
||||
|
||||
.box-wrapper {
|
||||
background: alpha(@base, 0.95);
|
||||
padding: 20px;
|
||||
border: 2px solid @border;
|
||||
}
|
||||
|
||||
.preview-box {
|
||||
}
|
||||
|
||||
.box {
|
||||
}
|
||||
|
||||
.search-container {
|
||||
background: @base;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.input placeholder {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.input {
|
||||
}
|
||||
|
||||
.input:focus,
|
||||
.input:active {
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.content-container {
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
}
|
||||
|
||||
.scroll {
|
||||
}
|
||||
|
||||
.list {
|
||||
}
|
||||
|
||||
child,
|
||||
child > * {
|
||||
}
|
||||
|
||||
child:hover .item-box {
|
||||
}
|
||||
|
||||
child:selected .item-box {
|
||||
}
|
||||
|
||||
child:selected .item-box * {
|
||||
color: @selected_text;
|
||||
}
|
||||
|
||||
.item-box {
|
||||
padding-left: 14px;
|
||||
}
|
||||
|
||||
.item-text-box {
|
||||
all: unset;
|
||||
padding: 14px 0;
|
||||
}
|
||||
|
||||
.item-text {
|
||||
}
|
||||
|
||||
.item-subtext {
|
||||
font-size: 0px;
|
||||
min-height: 0px;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.item-image {
|
||||
margin-right: 14px;
|
||||
-gtk-icon-transform: scale(0.9);
|
||||
}
|
||||
|
||||
.current {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.keybind-hints {
|
||||
background: @background;
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.preview {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
* Css Colors
|
||||
* Generated with Matugen
|
||||
*/
|
||||
<* for name, value in colors *>
|
||||
@define-color {{name}} {{value.default.hex}};
|
||||
<* endfor *>
|
||||
@@ -0,0 +1,41 @@
|
||||
set default-bg "#{{colors.surface.default.hex_stripped}}"
|
||||
set default-fg "#{{colors.on_surface.default.hex_stripped}}"
|
||||
|
||||
set statusbar-bg "#{{colors.surface.default.hex_stripped}}"
|
||||
set statusbar-fg "#{{colors.on_surface.default.hex_stripped}}"
|
||||
|
||||
set inputbar-bg "#{{colors.surface.default.hex_stripped}}"
|
||||
set inputbar-fg "#{{colors.on_surface.default.hex_stripped}}"
|
||||
|
||||
set notification-bg "#{{colors.surface.default.hex_stripped}}"
|
||||
set notification-fg "#{{colors.on_surface.default.hex_stripped}}"
|
||||
|
||||
set notification-error-bg "#{{colors.error.default.hex_stripped}}"
|
||||
set notification-error-fg "#{{colors.on_error.default.hex_stripped}}"
|
||||
|
||||
set notification-warning-bg "#{{colors.tertiary.default.hex_stripped}}"
|
||||
set notification-warning-fg "#{{colors.on_tertiary.default.hex_stripped}}"
|
||||
|
||||
set highlight-color "#{{colors.tertiary.default.hex_stripped}}"
|
||||
set highlight-active-color "#{{colors.secondary.default.hex_stripped}}"
|
||||
|
||||
set completion-bg "#{{colors.surface.default.hex_stripped}}"
|
||||
set completion-fg "#{{colors.on_surface.default.hex_stripped}}"
|
||||
|
||||
set completion-group-bg "#{{colors.surface.default.hex_stripped}}"
|
||||
set completion-group-fg "#{{colors.on_surface.default.hex_stripped}}"
|
||||
|
||||
set completion-highlight-bg "#{{colors.on_surface.default.hex_stripped}}"
|
||||
set completion-highlight-fg "#{{colors.surface.default.hex_stripped}}"
|
||||
|
||||
set index-bg "#{{colors.surface.default.hex_stripped}}"
|
||||
set index-fg "#{{colors.on_surface.default.hex_stripped}}"
|
||||
|
||||
set index-active-bg "#{{colors.surface_container.default.hex_stripped}}"
|
||||
set index-active-fg "#{{colors.on_surface.default.hex_stripped}}"
|
||||
|
||||
set render-loading-bg "#{{colors.surface.default.hex_stripped}}"
|
||||
set render-loading-fg "#{{colors.on_surface.default.hex_stripped}}"
|
||||
|
||||
set recolor-lightcolor "#{{colors.surface.default.hex_stripped}}"
|
||||
set recolor-darkcolor "#{{colors.on_surface.default.hex_stripped}}"
|
||||
@@ -0,0 +1,39 @@
|
||||
{pkgs, ...}: {
|
||||
programs.mpv = {
|
||||
enable = true;
|
||||
scripts = with pkgs.mpvScripts; [
|
||||
uosc
|
||||
thumbfast
|
||||
];
|
||||
config = {
|
||||
# uosc provides its own UI
|
||||
osc = "no";
|
||||
osd-bar = "no";
|
||||
border = "no";
|
||||
|
||||
# Subtitle preferences - prefer full subtitles over forced
|
||||
# slang = "eng,en,enm"; # English subtitle preference order
|
||||
# subs-fallback = "default"; # Use default if preferred not found
|
||||
# sub-forced-events-only = "no"; # Don't limit to forced subtitle events
|
||||
};
|
||||
};
|
||||
|
||||
xdg.mimeApps = {
|
||||
enable = true;
|
||||
defaultApplications = {
|
||||
"video/mp4" = "mpv.desktop";
|
||||
"video/mkv" = "mpv.desktop";
|
||||
"video/webm" = "mpv.desktop";
|
||||
"video/avi" = "mpv.desktop";
|
||||
"video/x-matroska" = "mpv.desktop";
|
||||
"video/quicktime" = "mpv.desktop";
|
||||
};
|
||||
};
|
||||
|
||||
wayland.windowManager.hyprland.settings.windowrulev2 = [
|
||||
# --- VIDEO PLAYER (mpv) ---
|
||||
"float, class:^(mpv)$"
|
||||
"center, class:^(mpv)$"
|
||||
"size 60% 70%, class:^(mpv)$"
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
inputs,
|
||||
system,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
home.packages = [
|
||||
# FIXME: does not dynamically update with matugen when open
|
||||
inputs.nixovim.packages.${pkgs.system}.full
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{pkgs, ...}: {
|
||||
home.packages = with pkgs; [
|
||||
nextcloud-client
|
||||
];
|
||||
|
||||
wayland.windowManager.hyprland.settings.exec-once = [
|
||||
"uwsm app -- nextcloud --background"
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{pkgs, ...}: {
|
||||
home.packages = [
|
||||
pkgs.playerctl
|
||||
];
|
||||
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
bindl = [
|
||||
", XF86AudioPlay, exec, playerctl play-pause && notify-send -u low -t 1000 \"Media\" \"$(playerctl status)\""
|
||||
", XF86AudioPrev, exec, playerctl previous && notify-send -u low -t 1000 \"Previous Track\" \"$(playerctl metadata title)\""
|
||||
", XF86AudioNext, exec, playerctl next && notify-send -u low -t 1000 \"Next Track\" \"$(playerctl metadata title)\""
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{ pkgs }:
|
||||
|
||||
pkgs.stdenv.mkDerivation {
|
||||
pname = "hakase-plymouth-theme";
|
||||
version = "1.0";
|
||||
|
||||
src = ./themes/hakase;
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/share/plymouth/themes/hakase
|
||||
cp * $out/share/plymouth/themes/hakase/
|
||||
|
||||
# Patch the .plymouth file to point to the store path
|
||||
sed -i "s@ImageDir=.*@ImageDir=$out/share/plymouth/themes/hakase@" $out/share/plymouth/themes/hakase/hakase.plymouth
|
||||
sed -i "s@ScriptFile=.*@ScriptFile=$out/share/plymouth/themes/hakase/hakase.script@" $out/share/plymouth/themes/hakase/hakase.plymouth
|
||||
'';
|
||||
}
|
||||
|
After Width: | Height: | Size: 293 B |
|
After Width: | Height: | Size: 694 B |
@@ -0,0 +1,11 @@
|
||||
[Plymouth Theme]
|
||||
Name=Omarchy
|
||||
Description=Omarchy splash screen.
|
||||
ModuleName=script
|
||||
|
||||
[script]
|
||||
ImageDir=/usr/share/plymouth/themes/omarchy
|
||||
ScriptFile=/usr/share/plymouth/themes/omarchy/omarchy.script
|
||||
ConsoleLogBackgroundColor=0x1a1b26
|
||||
MonospaceFont=Cantarell 11
|
||||
Font=Cantarell 11
|
||||
@@ -0,0 +1,257 @@
|
||||
# Omarchy Plymouth Theme Script
|
||||
|
||||
Window.SetBackgroundTopColor(0.176, 0.067, 0.165);
|
||||
Window.SetBackgroundBottomColor(0.176, 0.067, 0.165);
|
||||
|
||||
logo.image = Image("logo.png");
|
||||
logo.sprite = Sprite(logo.image);
|
||||
logo.sprite.SetX (Window.GetWidth() / 2 - logo.image.GetWidth() / 2);
|
||||
logo.sprite.SetY (Window.GetHeight() / 2 - logo.image.GetHeight() / 2);
|
||||
logo.sprite.SetOpacity (1);
|
||||
|
||||
# Use these to adjust the progress bar timing
|
||||
global.fake_progress_limit = 0.7; # Target percentage for fake progress (0.0 to 1.0)
|
||||
global.fake_progress_duration = 15.0; # Duration in seconds to reach limit
|
||||
|
||||
# Progress bar animation variables
|
||||
global.fake_progress = 0.0;
|
||||
global.real_progress = 0.0;
|
||||
global.fake_progress_active = 0; # 0 / 1 boolean
|
||||
global.animation_frame = 0;
|
||||
global.fake_progress_start_time = 0; # Track when fake progress started
|
||||
global.password_shown = 0; # Track if password dialog has been shown
|
||||
global.max_progress = 0.0; # Track the maximum progress reached to prevent backwards movement
|
||||
|
||||
fun refresh_callback ()
|
||||
{
|
||||
global.animation_frame++;
|
||||
|
||||
# Animate fake progress to limit over time with easing
|
||||
if (global.fake_progress_active == 1)
|
||||
{
|
||||
# Calculate elapsed time since start
|
||||
elapsed_time = global.animation_frame / 50.0; # Convert frames to seconds (50 FPS)
|
||||
|
||||
# Calculate linear progress ratio (0 to 1) based on time
|
||||
time_ratio = elapsed_time / global.fake_progress_duration;
|
||||
if (time_ratio > 1.0)
|
||||
time_ratio = 1.0;
|
||||
|
||||
# Apply easing curve: ease-out quadratic
|
||||
# Formula: 1 - (1 - x)^2
|
||||
eased_ratio = 1 - ((1 - time_ratio) * (1 - time_ratio));
|
||||
|
||||
# Calculate fake progress based on eased ratio
|
||||
global.fake_progress = eased_ratio * global.fake_progress_limit;
|
||||
|
||||
# Update progress bar with fake progress
|
||||
update_progress_bar(global.fake_progress);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Plymouth.SetRefreshFunction (refresh_callback);
|
||||
|
||||
#----------------------------------------- Helper Functions --------------------------------
|
||||
|
||||
fun update_progress_bar(progress)
|
||||
{
|
||||
# Only update if progress is moving forward
|
||||
if (progress > global.max_progress)
|
||||
{
|
||||
global.max_progress = progress;
|
||||
width = Math.Int(progress_bar.original_image.GetWidth() * progress);
|
||||
if (width < 1) width = 1; # Ensure minimum width of 1 pixel
|
||||
|
||||
progress_bar.image = progress_bar.original_image.Scale(width, progress_bar.original_image.GetHeight());
|
||||
progress_bar.sprite.SetImage(progress_bar.image);
|
||||
}
|
||||
}
|
||||
|
||||
fun show_progress_bar()
|
||||
{
|
||||
progress_box.sprite.SetOpacity(1);
|
||||
progress_bar.sprite.SetOpacity(1);
|
||||
}
|
||||
|
||||
fun hide_progress_bar()
|
||||
{
|
||||
progress_box.sprite.SetOpacity(0);
|
||||
progress_bar.sprite.SetOpacity(0);
|
||||
}
|
||||
|
||||
fun show_password_dialog()
|
||||
{
|
||||
lock.sprite.SetOpacity(1);
|
||||
entry.sprite.SetOpacity(1);
|
||||
}
|
||||
|
||||
fun hide_password_dialog()
|
||||
{
|
||||
lock.sprite.SetOpacity(0);
|
||||
entry.sprite.SetOpacity(0);
|
||||
for (index = 0; bullet.sprites[index]; index++)
|
||||
bullet.sprites[index].SetOpacity(0);
|
||||
}
|
||||
|
||||
fun start_fake_progress()
|
||||
{
|
||||
# Don't reset if we already have progress
|
||||
if (global.max_progress == 0.0)
|
||||
{
|
||||
global.fake_progress = 0.0;
|
||||
global.real_progress = 0.0;
|
||||
update_progress_bar(0.0);
|
||||
}
|
||||
global.fake_progress_active = 1;
|
||||
global.animation_frame = 0;
|
||||
}
|
||||
|
||||
fun stop_fake_progress()
|
||||
{
|
||||
global.fake_progress_active = 0;
|
||||
}
|
||||
|
||||
#----------------------------------------- Dialogue --------------------------------
|
||||
|
||||
lock.image = Image("lock.png");
|
||||
entry.image = Image("entry.png");
|
||||
bullet.image = Image("bullet.png");
|
||||
|
||||
entry.sprite = Sprite(entry.image);
|
||||
entry.x = Window.GetWidth()/2 - entry.image.GetWidth() / 2;
|
||||
entry.y = logo.sprite.GetY() + logo.image.GetHeight() + 40;
|
||||
entry.sprite.SetPosition(entry.x, entry.y, 10001);
|
||||
entry.sprite.SetOpacity(0);
|
||||
|
||||
# Scale lock to be slightly shorter than entry field height
|
||||
# Original lock is 84x96, entry height determines scale
|
||||
lock_height = entry.image.GetHeight() * 0.8;
|
||||
lock_scale = lock_height / 96;
|
||||
lock_width = 84 * lock_scale;
|
||||
|
||||
scaled_lock = lock.image.Scale(lock_width, lock_height);
|
||||
lock.sprite = Sprite(scaled_lock);
|
||||
lock.x = entry.x - lock_width - 15;
|
||||
lock.y = entry.y + entry.image.GetHeight()/2 - lock_height/2;
|
||||
lock.sprite.SetPosition(lock.x, lock.y, 10001);
|
||||
lock.sprite.SetOpacity(0);
|
||||
|
||||
# Bullet array
|
||||
bullet.sprites = [];
|
||||
|
||||
fun display_normal_callback ()
|
||||
{
|
||||
hide_password_dialog();
|
||||
|
||||
# Get current mode
|
||||
mode = Plymouth.GetMode();
|
||||
|
||||
# Only show progress bar for boot and resume modes
|
||||
if ((mode == "boot" || mode == "resume") && global.password_shown == 1)
|
||||
{
|
||||
show_progress_bar();
|
||||
start_fake_progress();
|
||||
}
|
||||
}
|
||||
|
||||
fun display_password_callback (prompt, bullets)
|
||||
{
|
||||
global.password_shown = 1; # Mark that password dialog has been shown
|
||||
|
||||
# Reset progress when password dialog appears
|
||||
stop_fake_progress();
|
||||
hide_progress_bar();
|
||||
global.max_progress = 0.0;
|
||||
global.fake_progress = 0.0;
|
||||
global.real_progress = 0.0;
|
||||
show_password_dialog();
|
||||
|
||||
# Clear all bullets first
|
||||
for (index = 0; bullet.sprites[index]; index++)
|
||||
bullet.sprites[index].SetOpacity(0);
|
||||
|
||||
# Create and show bullets for current password (max 21)
|
||||
max_bullets = 21;
|
||||
bullets_to_show = bullets;
|
||||
if (bullets_to_show > max_bullets)
|
||||
bullets_to_show = max_bullets;
|
||||
|
||||
for (index = 0; index < bullets_to_show; index++)
|
||||
{
|
||||
if (!bullet.sprites[index])
|
||||
{
|
||||
# Scale bullet image to 7x7 pixels
|
||||
scaled_bullet = bullet.image.Scale(7, 7);
|
||||
bullet.sprites[index] = Sprite(scaled_bullet);
|
||||
bullet.x = entry.x + 20 + index * (7 + 5);
|
||||
bullet.y = entry.y + entry.image.GetHeight() / 2 - 3.5;
|
||||
bullet.sprites[index].SetPosition(bullet.x, bullet.y, 10002);
|
||||
}
|
||||
bullet.sprites[index].SetOpacity(1);
|
||||
}
|
||||
}
|
||||
|
||||
Plymouth.SetDisplayNormalFunction(display_normal_callback);
|
||||
Plymouth.SetDisplayPasswordFunction(display_password_callback);
|
||||
|
||||
#----------------------------------------- Progress Bar --------------------------------
|
||||
|
||||
progress_box.image = Image("progress_box.png");
|
||||
progress_box.sprite = Sprite(progress_box.image);
|
||||
|
||||
progress_box.x = Window.GetWidth() / 2 - progress_box.image.GetWidth() / 2;
|
||||
progress_box.y = entry.y + entry.image.GetHeight() / 2 - progress_box.image.GetHeight() / 2;
|
||||
progress_box.sprite.SetPosition(progress_box.x, progress_box.y, 0);
|
||||
progress_box.sprite.SetOpacity(0);
|
||||
|
||||
progress_bar.original_image = Image("progress_bar.png");
|
||||
progress_bar.sprite = Sprite();
|
||||
progress_bar.image = progress_bar.original_image.Scale(1, progress_bar.original_image.GetHeight());
|
||||
|
||||
progress_bar.x = Window.GetWidth() / 2 - progress_bar.original_image.GetWidth() / 2;
|
||||
progress_bar.y = progress_box.y + (progress_box.image.GetHeight() - progress_bar.original_image.GetHeight()) / 2;
|
||||
progress_bar.sprite.SetPosition(progress_bar.x, progress_bar.y, 1);
|
||||
progress_bar.sprite.SetOpacity(0);
|
||||
|
||||
fun progress_callback (duration, progress)
|
||||
{
|
||||
global.real_progress = progress;
|
||||
|
||||
# If real progress is above limit, stop fake progress and use real progress
|
||||
if (progress > global.fake_progress_limit)
|
||||
{
|
||||
stop_fake_progress();
|
||||
update_progress_bar(progress);
|
||||
}
|
||||
}
|
||||
|
||||
Plymouth.SetBootProgressFunction(progress_callback);
|
||||
|
||||
#----------------------------------------- Quit --------------------------------
|
||||
|
||||
fun quit_callback ()
|
||||
{
|
||||
logo.sprite.SetOpacity (1);
|
||||
}
|
||||
|
||||
Plymouth.SetQuitFunction(quit_callback);
|
||||
|
||||
#----------------------------------------- Message --------------------------------
|
||||
|
||||
message_sprite = Sprite();
|
||||
message_sprite.SetPosition(10, 10, 10000);
|
||||
|
||||
fun display_message_callback (text)
|
||||
{
|
||||
my_image = Image.Text(text, 1, 1, 1);
|
||||
message_sprite.SetImage(my_image);
|
||||
}
|
||||
|
||||
fun hide_message_callback (text)
|
||||
{
|
||||
message_sprite.SetOpacity(0);
|
||||
}
|
||||
|
||||
Plymouth.SetDisplayMessageFunction (display_message_callback);
|
||||
Plymouth.SetHideMessageFunction (hide_message_callback);
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 314 B |
|
After Width: | Height: | Size: 314 B |
@@ -0,0 +1,4 @@
|
||||
{pkgs, ...}: {
|
||||
environment.systemPackages = with pkgs; [via];
|
||||
services.udev.packages = with pkgs; [via];
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
{pkgs, myConfig, ...}: let
|
||||
# Screenshot script with swappy integration
|
||||
screenshot = pkgs.writeShellScriptBin "screenshot" ''
|
||||
#!/usr/bin/env bash
|
||||
|
||||
case "$1" in
|
||||
region)
|
||||
# Select region and edit
|
||||
grim -g "$(slurp)" - | swappy -f -
|
||||
;;
|
||||
window)
|
||||
# Screenshot active window
|
||||
grim -g "$(hyprctl -j activewindow | jq -r '"\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"')" - | swappy -f -
|
||||
;;
|
||||
screen)
|
||||
# Screenshot current monitor
|
||||
grim -o "$(hyprctl -j monitors | jq -r '.[] | select(.focused) | .name')" - | swappy -f -
|
||||
;;
|
||||
all)
|
||||
# Screenshot all monitors
|
||||
grim - | swappy -f -
|
||||
;;
|
||||
region-save)
|
||||
# Quick region screenshot (save without editing and copy to clipboard)
|
||||
filepath=~/Pictures/Screenshots/$(date +'%Y-%m-%d_%H-%M-%S.png')
|
||||
grim -g "$(slurp)" "$filepath"
|
||||
wl-copy < "$filepath"
|
||||
notify-send "Screenshot saved" "Saved and copied to clipboard"
|
||||
;;
|
||||
ocr)
|
||||
# OCR Selection
|
||||
grim -g "$(slurp)" - | tesseract stdin stdout | wl-copy
|
||||
notify-send "OCR" "Text extracted to clipboard"
|
||||
;;
|
||||
*)
|
||||
echo "Usage: screenshot {region|window|screen|all|region-save|ocr}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
'';
|
||||
in {
|
||||
home.packages = with pkgs; [
|
||||
grim # Screenshot utility
|
||||
slurp # Region selector
|
||||
swappy # Annotation tool
|
||||
jq # For window selection
|
||||
wl-clipboard # For copying to clipboard
|
||||
tesseract # OCR tool
|
||||
screenshot # Our wrapper script
|
||||
];
|
||||
|
||||
# Create Screenshots directory
|
||||
home.file."Pictures/Screenshots/.keep".text = "";
|
||||
|
||||
# Swappy configuration
|
||||
home.file.".config/swappy/config".text = ''
|
||||
[Default]
|
||||
save_dir=$HOME/Pictures/Screenshots
|
||||
save_filename_format=screenshot_%Y%m%d_%H%M%S.png
|
||||
show_panel=true
|
||||
line_size=5
|
||||
text_size=20
|
||||
text_font=${myConfig.font.sans}
|
||||
paint_mode=brush
|
||||
early_exit=false
|
||||
fill_shape=false
|
||||
'';
|
||||
|
||||
wayland.windowManager.hyprland.settings.bindd = [
|
||||
# Screenshots
|
||||
"SUPER, S, Screenshot Region (with edit), exec, screenshot region"
|
||||
"SUPER SHIFT, S, Screenshot Active Window, exec, screenshot window"
|
||||
"SUPER ALT, S, Quick Screenshot (no edit), exec, screenshot region-save"
|
||||
"SUPER ALT SHIFT, S, Screenshot Current Monitor, exec, screenshot screen"
|
||||
"SUPER ALT, E, OCR Selection, exec, screenshot ocr"
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
services.swayosd.enable = true;
|
||||
|
||||
# Auto-restart swayosd on crash
|
||||
systemd.user.services.swayosd = {
|
||||
Unit = {
|
||||
StartLimitBurst = lib.mkForce 5;
|
||||
StartLimitIntervalSec = lib.mkForce 30;
|
||||
After = [ "graphical-session.target" ];
|
||||
PartOf = [ "graphical-session.target" ];
|
||||
};
|
||||
Service = {
|
||||
Restart = lib.mkForce "on-failure";
|
||||
RestartSec = lib.mkForce "1s";
|
||||
};
|
||||
Install.WantedBy = [ "graphical-session.target" ];
|
||||
};
|
||||
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
bindel = [
|
||||
", XF86AudioRaiseVolume, exec, swayosd-client --output-volume raise"
|
||||
", XF86AudioLowerVolume, exec, swayosd-client --output-volume lower"
|
||||
];
|
||||
bindl = [
|
||||
", XF86AudioMute, exec, swayosd-client --output-volume mute-toggle"
|
||||
", Caps_Lock, exec, sleep 0.1 && swayosd-client --caps-lock"
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
home.packages = with pkgs; [ tickrs ];
|
||||
|
||||
xdg.configFile."tickrs/config.yml".text = ''
|
||||
symbols:
|
||||
- NVDA
|
||||
- AMD
|
||||
- LAC
|
||||
- ONDS
|
||||
- SLV
|
||||
- GOOGL
|
||||
- TSM
|
||||
show_volumes: true
|
||||
show_x_axis: true
|
||||
show_y_axis: true
|
||||
time_frame: Day1
|
||||
update_frequency: 1
|
||||
chart_type: candle
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{pkgs, ...}: let
|
||||
hakase-screensaver-launch = pkgs.writeShellScriptBin "hakase-cmd-screensaver" ''
|
||||
# Placeholder for actual screensaver logic if needed
|
||||
echo "Screensaver placeholder"
|
||||
'';
|
||||
in {
|
||||
home.packages = with pkgs; [
|
||||
terminaltexteffects
|
||||
hakase-screensaver-launch
|
||||
];
|
||||
home.file.".config/hakase/branding/screensaver.txt" = {
|
||||
source = ../../assets/branding.txt;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{ pkgs, ... }: {
|
||||
home.packages = with pkgs; [
|
||||
ttyper
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
...
|
||||
}: let
|
||||
vicinae-toggle = pkgs.writeShellScriptBin "vicinae-toggle" ''
|
||||
VICINAE_BIN="${inputs.vicinae.packages.${pkgs.system}.default}/bin/vicinae"
|
||||
ARGS=("$@")
|
||||
if [ ''${#ARGS[@]} -eq 0 ]; then
|
||||
ARGS=("toggle")
|
||||
fi
|
||||
|
||||
if ! "$VICINAE_BIN" "''${ARGS[@]}" 2>/dev/null; then
|
||||
${pkgs.systemd}/bin/systemctl --user restart vicinae || "$VICINAE_BIN" server &
|
||||
sleep 0.4
|
||||
exec "$VICINAE_BIN" "''${ARGS[@]}"
|
||||
fi
|
||||
'';
|
||||
in {
|
||||
services.vicinae = {
|
||||
enable = true;
|
||||
systemd = {
|
||||
enable = true;
|
||||
autoStart = true;
|
||||
environment = {
|
||||
USE_LAYER_SHELL = 1;
|
||||
};
|
||||
};
|
||||
|
||||
settings = {
|
||||
# Escape closes window (vim-like :q behavior)
|
||||
escape_key_behavior = "close_window";
|
||||
pop_to_root_on_close = true;
|
||||
close_on_unfocus = true;
|
||||
|
||||
keybinds = {
|
||||
# UI shortcuts
|
||||
"open-search-filter" = "control+/"; # vim search
|
||||
"open-settings" = "control+,";
|
||||
"toggle-action-panel" = "control+B";
|
||||
|
||||
# Vim-like action keybinds
|
||||
"action.move-up" = "control+shift+K";
|
||||
"action.move-down" = "control+shift+J";
|
||||
"action.copy" = "control+Y"; # yank
|
||||
"action.copy-name" = "control+shift+Y";
|
||||
"action.remove" = "control+D"; # delete
|
||||
"action.dangerous-remove" = "control+shift+D";
|
||||
"action.edit" = "control+E";
|
||||
"action.open" = "control+O";
|
||||
"action.refresh" = "control+R";
|
||||
"action.pin" = "control+P";
|
||||
"action.new" = "control+N";
|
||||
"action.save" = "control+S";
|
||||
};
|
||||
theme = {
|
||||
light = {
|
||||
name = "matugen";
|
||||
icon_theme = "Papirus-Dark";
|
||||
};
|
||||
dark = {
|
||||
name = "matugen";
|
||||
icon_theme = "Papirus-Dark";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Ensure vicinae themes directory exists for matugen output
|
||||
home.file.".local/share/vicinae/themes/.keep".text = "";
|
||||
|
||||
home.packages = [vicinae-toggle];
|
||||
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
exec-once = [
|
||||
"vicinae server"
|
||||
];
|
||||
|
||||
bindd = [
|
||||
"SUPER, SPACE, Open Vicinae, exec, vicinae-toggle"
|
||||
"SUPER, period, Open Emoji Picker, exec, vicinae-toggle deeplink vicinae://extensions/vicinae/core/search-emojis"
|
||||
# FIXME: calculator history does not allow you to calculate
|
||||
"SUPER, C, Open Calculator, exec, vicinae-toggle deeplink vicinae://extensions/vicinae/calculator/history"
|
||||
"SUPER, V, Open Clipboard History, exec, vicinae-toggle deeplink vicinae://extensions/vicinae/clipboard/history"
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,579 @@
|
||||
{
|
||||
inputs,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
exec-once = [
|
||||
"uwsm app -- elephant"
|
||||
"walker --gapplication-service"
|
||||
];
|
||||
};
|
||||
imports = [
|
||||
# ./style.nix
|
||||
./layout.nix
|
||||
];
|
||||
|
||||
programs.walker = {
|
||||
enable = true;
|
||||
runAsService = true;
|
||||
package = inputs.walker.packages.${pkgs.system}.default;
|
||||
|
||||
# CSS Implementation using Stylix Colors
|
||||
config = {
|
||||
# General Settings
|
||||
force_keyboard_focus = true;
|
||||
close_when_open = true;
|
||||
click_to_close = true;
|
||||
single_click_activation = true;
|
||||
selection_wrap = true;
|
||||
global_argument_delimiter = "#";
|
||||
exact_search_prefix = "'";
|
||||
# theme = "default";
|
||||
disable_mouse = false;
|
||||
debug = false;
|
||||
page_jump_items = 10;
|
||||
hide_quick_activation = true;
|
||||
hide_action_hints = true;
|
||||
hide_action_hints_dmenu = true;
|
||||
hide_return_action = false;
|
||||
resume_last_query = false;
|
||||
actions_as_menu = false;
|
||||
|
||||
# Shell positioning
|
||||
shell = {
|
||||
anchor_top = true;
|
||||
anchor_bottom = true;
|
||||
anchor_left = true;
|
||||
anchor_right = true;
|
||||
};
|
||||
|
||||
# Column config
|
||||
columns.symbols = 3;
|
||||
|
||||
# Placeholders
|
||||
placeholders.default = {
|
||||
input = "Search";
|
||||
list = "No Results";
|
||||
};
|
||||
|
||||
# Keybinds
|
||||
keybinds = {
|
||||
close = ["Escape"];
|
||||
next = ["Down"];
|
||||
previous = ["Up"];
|
||||
left = ["Left"];
|
||||
right = ["Right"];
|
||||
down = ["Down"];
|
||||
up = ["Up"];
|
||||
toggle_exact = ["ctrl e"];
|
||||
resume_last_query = ["ctrl r"];
|
||||
quick_activate = ["F1" "F2" "F3" "F4"];
|
||||
page_down = ["Page_Down"];
|
||||
page_up = ["Page_Up"];
|
||||
show_actions = ["alt j"];
|
||||
};
|
||||
|
||||
# Providers General
|
||||
providers = {
|
||||
default = ["desktopapplications" "calc" "websearch"];
|
||||
empty = ["desktopapplications"];
|
||||
ignore_preview = [];
|
||||
max_results = 50;
|
||||
|
||||
argument_delimiter.runner = " ";
|
||||
|
||||
clipboard.time_format = "%d.%m. - %H:%M";
|
||||
|
||||
# Provider Prefixes
|
||||
prefixes = [
|
||||
{
|
||||
prefix = ";";
|
||||
provider = "providerlist";
|
||||
}
|
||||
{
|
||||
prefix = ">";
|
||||
provider = "runner";
|
||||
}
|
||||
{
|
||||
prefix = "/";
|
||||
provider = "files";
|
||||
}
|
||||
{
|
||||
prefix = ".";
|
||||
provider = "symbols";
|
||||
}
|
||||
{
|
||||
prefix = "!";
|
||||
provider = "todo";
|
||||
}
|
||||
{
|
||||
prefix = "%";
|
||||
provider = "bookmarks";
|
||||
}
|
||||
{
|
||||
prefix = "=";
|
||||
provider = "calc";
|
||||
}
|
||||
{
|
||||
prefix = "@";
|
||||
provider = "websearch";
|
||||
}
|
||||
{
|
||||
prefix = ":";
|
||||
provider = "clipboard";
|
||||
}
|
||||
{
|
||||
prefix = "$";
|
||||
provider = "windows";
|
||||
}
|
||||
];
|
||||
|
||||
# Actions
|
||||
actions = {
|
||||
fallback = [
|
||||
{
|
||||
action = "menus:open";
|
||||
label = "open";
|
||||
after = "Nothing";
|
||||
}
|
||||
{
|
||||
action = "menus:default";
|
||||
label = "run";
|
||||
after = "Close";
|
||||
}
|
||||
{
|
||||
action = "menus:parent";
|
||||
label = "back";
|
||||
bind = "Escape";
|
||||
after = "Nothing";
|
||||
}
|
||||
{
|
||||
action = "erase_history";
|
||||
label = "clear hist";
|
||||
bind = "ctrl h";
|
||||
after = "AsyncReload";
|
||||
}
|
||||
];
|
||||
dmenu = [
|
||||
{
|
||||
action = "select";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
}
|
||||
];
|
||||
providerlist = [
|
||||
{
|
||||
action = "activate";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
after = "ClearReload";
|
||||
}
|
||||
];
|
||||
bluetooth = [
|
||||
{
|
||||
action = "find";
|
||||
bind = "ctrl f";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
{
|
||||
action = "remove";
|
||||
bind = "ctrl d";
|
||||
after = "AsyncReload";
|
||||
}
|
||||
{
|
||||
action = "trust";
|
||||
bind = "ctrl t";
|
||||
after = "AsyncReload";
|
||||
}
|
||||
{
|
||||
action = "untrust";
|
||||
bind = "ctrl t";
|
||||
after = "AsyncReload";
|
||||
}
|
||||
{
|
||||
action = "pair";
|
||||
bind = "Return";
|
||||
after = "AsyncReload";
|
||||
}
|
||||
{
|
||||
action = "connect";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
after = "AsyncReload";
|
||||
}
|
||||
{
|
||||
action = "disconnect";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
after = "AsyncReload";
|
||||
}
|
||||
];
|
||||
archlinuxpkgs = [
|
||||
{
|
||||
action = "install";
|
||||
bind = "Return";
|
||||
default = true;
|
||||
}
|
||||
{
|
||||
action = "remove";
|
||||
bind = "Return";
|
||||
}
|
||||
{
|
||||
action = "show_all";
|
||||
label = "show all";
|
||||
bind = "ctrl i";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
{
|
||||
action = "refresh";
|
||||
label = "refresh";
|
||||
bind = "ctrl r";
|
||||
after = "AsyncReload";
|
||||
}
|
||||
{
|
||||
action = "visit_url";
|
||||
label = "open URL";
|
||||
bind = "ctrl o";
|
||||
}
|
||||
{
|
||||
action = "show_installed";
|
||||
label = "show installed";
|
||||
bind = "ctrl i";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
];
|
||||
calc = [
|
||||
{
|
||||
action = "copy";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
}
|
||||
{
|
||||
action = "delete";
|
||||
bind = "ctrl d";
|
||||
after = "AsyncReload";
|
||||
}
|
||||
{
|
||||
action = "save";
|
||||
bind = "ctrl s";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
];
|
||||
websearch = [
|
||||
{
|
||||
action = "search";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
}
|
||||
{
|
||||
action = "open_url";
|
||||
label = "open url";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
}
|
||||
];
|
||||
desktopapplications = [
|
||||
{
|
||||
action = "start";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
}
|
||||
{
|
||||
action = "start:keep";
|
||||
label = "open+next";
|
||||
bind = "shift Return";
|
||||
after = "KeepOpen";
|
||||
}
|
||||
{
|
||||
action = "new_instance";
|
||||
label = "new instance";
|
||||
bind = "ctrl Return";
|
||||
}
|
||||
{
|
||||
action = "new_instance:keep";
|
||||
label = "new+next";
|
||||
bind = "ctrl alt Return";
|
||||
after = "KeepOpen";
|
||||
}
|
||||
{
|
||||
action = "pin";
|
||||
bind = "ctrl p";
|
||||
after = "AsyncReload";
|
||||
}
|
||||
{
|
||||
action = "unpin";
|
||||
bind = "ctrl p";
|
||||
after = "AsyncReload";
|
||||
}
|
||||
{
|
||||
action = "pinup";
|
||||
bind = "ctrl n";
|
||||
after = "AsyncReload";
|
||||
}
|
||||
{
|
||||
action = "pindown";
|
||||
bind = "ctrl m";
|
||||
after = "AsyncReload";
|
||||
}
|
||||
];
|
||||
files = [
|
||||
{
|
||||
action = "open";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
}
|
||||
{
|
||||
action = "opendir";
|
||||
label = "open dir";
|
||||
bind = "ctrl Return";
|
||||
}
|
||||
{
|
||||
action = "copypath";
|
||||
label = "copy path";
|
||||
bind = "ctrl shift c";
|
||||
}
|
||||
{
|
||||
action = "copyfile";
|
||||
label = "copy file";
|
||||
bind = "ctrl c";
|
||||
}
|
||||
{
|
||||
action = "localsend";
|
||||
label = "localsend";
|
||||
bind = "ctrl l";
|
||||
}
|
||||
{
|
||||
action = "refresh_index";
|
||||
label = "reload";
|
||||
bind = "ctrl r";
|
||||
after = "AsyncReload";
|
||||
}
|
||||
];
|
||||
# Note: "1password" key starts with a digit, must be quoted in Nix
|
||||
"1password" = [
|
||||
{
|
||||
action = "copy_password";
|
||||
label = "copy password";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
}
|
||||
{
|
||||
action = "copy_username";
|
||||
label = "copy username";
|
||||
bind = "shift Return";
|
||||
}
|
||||
{
|
||||
action = "copy_2fa";
|
||||
label = "copy 2fa";
|
||||
bind = "ctrl Return";
|
||||
}
|
||||
];
|
||||
todo = [
|
||||
{
|
||||
action = "save";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
{
|
||||
action = "save_next";
|
||||
label = "save & new";
|
||||
bind = "shift Return";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
{
|
||||
action = "delete";
|
||||
bind = "ctrl d";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
{
|
||||
action = "active";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
after = "Nothing";
|
||||
}
|
||||
{
|
||||
action = "inactive";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
after = "Nothing";
|
||||
}
|
||||
{
|
||||
action = "done";
|
||||
bind = "ctrl f";
|
||||
after = "Nothing";
|
||||
}
|
||||
{
|
||||
action = "change_category";
|
||||
bind = "ctrl y";
|
||||
label = "change category";
|
||||
after = "Nothing";
|
||||
}
|
||||
{
|
||||
action = "clear";
|
||||
bind = "ctrl x";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
{
|
||||
action = "create";
|
||||
bind = "ctrl a";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
{
|
||||
action = "search";
|
||||
bind = "ctrl a";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
];
|
||||
runner = [
|
||||
{
|
||||
action = "run";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
}
|
||||
{
|
||||
action = "runterminal";
|
||||
label = "run in terminal";
|
||||
bind = "shift Return";
|
||||
}
|
||||
];
|
||||
symbols = [
|
||||
{
|
||||
action = "copy";
|
||||
label = "select";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
}
|
||||
];
|
||||
unicode = [
|
||||
{
|
||||
action = "copy";
|
||||
label = "select";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
}
|
||||
];
|
||||
nirisessions = [
|
||||
{
|
||||
action = "start";
|
||||
label = "start";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
}
|
||||
{
|
||||
action = "start_new";
|
||||
label = "start blank";
|
||||
bind = "ctrl Return";
|
||||
}
|
||||
];
|
||||
clipboard = [
|
||||
{
|
||||
action = "copy";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
}
|
||||
{
|
||||
action = "remove";
|
||||
bind = "ctrl d";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
{
|
||||
action = "remove_all";
|
||||
label = "clear";
|
||||
bind = "ctrl shift d";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
{
|
||||
action = "show_images_only";
|
||||
label = "only images";
|
||||
bind = "ctrl i";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
{
|
||||
action = "show_text_only";
|
||||
label = "only text";
|
||||
bind = "ctrl i";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
{
|
||||
action = "show_combined";
|
||||
label = "show all";
|
||||
bind = "ctrl i";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
{
|
||||
action = "pause";
|
||||
bind = "ctrl p";
|
||||
}
|
||||
{
|
||||
action = "unpause";
|
||||
bind = "ctrl p";
|
||||
}
|
||||
{
|
||||
action = "edit";
|
||||
bind = "ctrl o";
|
||||
}
|
||||
{
|
||||
action = "localsend";
|
||||
bind = "ctrl l";
|
||||
}
|
||||
];
|
||||
bookmarks = [
|
||||
{
|
||||
action = "save";
|
||||
bind = "Return";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
{
|
||||
action = "open";
|
||||
default = true;
|
||||
bind = "Return";
|
||||
}
|
||||
{
|
||||
action = "delete";
|
||||
bind = "ctrl d";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
{
|
||||
action = "change_category";
|
||||
label = "Change category";
|
||||
bind = "ctrl y";
|
||||
after = "Nothing";
|
||||
}
|
||||
{
|
||||
action = "change_browser";
|
||||
label = "Change browser";
|
||||
bind = "ctrl b";
|
||||
after = "Nothing";
|
||||
}
|
||||
{
|
||||
action = "import";
|
||||
label = "Import";
|
||||
bind = "ctrl i";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
{
|
||||
action = "create";
|
||||
bind = "ctrl a";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
{
|
||||
action = "search";
|
||||
bind = "ctrl a";
|
||||
after = "AsyncClearReload";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
home.file.".config/elephant/websearch.toml".text = ''
|
||||
[[entries]]
|
||||
name = "DuckDuckGo"
|
||||
url = "https://duckduckgo.com/?q=%TERM%"
|
||||
default = true
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
{
|
||||
home.file.".config/walker/themes/nixos/layout.xml".text = ''
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<requires lib="gtk" version="4.0"></requires>
|
||||
<object class="GtkWindow" id="Window">
|
||||
<style>
|
||||
<class name="window"></class>
|
||||
</style>
|
||||
<property name="resizable">true</property>
|
||||
<property name="title">Walker</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="BoxWrapper">
|
||||
<style>
|
||||
<class name="box-wrapper"></class>
|
||||
</style>
|
||||
<property name="width-request">644</property>
|
||||
<property name="overflow">hidden</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="halign">center</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="Box">
|
||||
<style>
|
||||
<class name="box"></class>
|
||||
</style>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="hexpand-set">true</property>
|
||||
<property name="hexpand">true</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="SearchContainer">
|
||||
<style>
|
||||
<class name="search-container"></class>
|
||||
</style>
|
||||
<property name="overflow">hidden</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="halign">fill</property>
|
||||
<property name="hexpand-set">true</property>
|
||||
<property name="hexpand">true</property>
|
||||
<child>
|
||||
<object class="GtkEntry" id="Input">
|
||||
<style>
|
||||
<class name="input"></class>
|
||||
</style>
|
||||
<property name="halign">fill</property>
|
||||
<property name="hexpand-set">true</property>
|
||||
<property name="hexpand">true</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="ContentContainer">
|
||||
<style>
|
||||
<class name="content-container"></class>
|
||||
</style>
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="spacing">10</property>
|
||||
<property name="vexpand">true</property>
|
||||
<property name="vexpand-set">true</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="ElephantHint">
|
||||
<style>
|
||||
<class name="elephant-hint"></class>
|
||||
</style>
|
||||
<property name="hexpand">true</property>
|
||||
<property name="height-request">100</property>
|
||||
<property name="label">Waiting for elephant...</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="Placeholder">
|
||||
<style>
|
||||
<class name="placeholder"></class>
|
||||
</style>
|
||||
<property name="label">No Results</property>
|
||||
<property name="yalign">0.0</property>
|
||||
<property name="hexpand">true</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="Scroll">
|
||||
<style>
|
||||
<class name="scroll"></class>
|
||||
</style>
|
||||
<property name="hexpand">true</property>
|
||||
<property name="can_focus">false</property>
|
||||
<property name="overlay-scrolling">true</property>
|
||||
<property name="max-content-width">600</property>
|
||||
<property name="max-content-height">300</property>
|
||||
<property name="min-content-height">0</property>
|
||||
<property name="propagate-natural-height">true</property>
|
||||
<property name="propagate-natural-width">true</property>
|
||||
<property name="hscrollbar-policy">automatic</property>
|
||||
<property name="vscrollbar-policy">automatic</property>
|
||||
<child>
|
||||
<object class="GtkGridView" id="List">
|
||||
<style>
|
||||
<class name="list"></class>
|
||||
</style>
|
||||
<property name="max_columns">1</property>
|
||||
<property name="can_focus">false</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="Preview">
|
||||
<style>
|
||||
<class name="preview"></class>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="Keybinds">
|
||||
<property name="hexpand">true</property>
|
||||
<property name="margin-top">10</property>
|
||||
<style>
|
||||
<class name="keybinds"></class>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkBox" id="GlobalKeybinds">
|
||||
<property name="spacing">10</property>
|
||||
<style>
|
||||
<class name="global-keybinds"></class>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="ItemKeybinds">
|
||||
<property name="hexpand">true</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="spacing">10</property>
|
||||
<style>
|
||||
<class name="item-keybinds"></class>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="Error">
|
||||
<style>
|
||||
<class name="error"></class>
|
||||
</style>
|
||||
<property name="xalign">0</property>
|
||||
<property name="visible">false</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
{config, ...}: {
|
||||
# themes."nixos".style = ''
|
||||
# @define-color window_bg_color #1f1f28;
|
||||
# @define-color accent_bg_color #54546d;
|
||||
# @define-color theme_fg_color #f2ecbc;
|
||||
# @define-color error_bg_color #C34043;
|
||||
# @define-color error_fg_color #DCD7BA;
|
||||
#
|
||||
# * {
|
||||
# all: unset;
|
||||
# }
|
||||
#
|
||||
# popover {
|
||||
# background: lighter(@window_bg_color);
|
||||
# border: 1px solid darker(@accent_bg_color);
|
||||
# border-radius: 18px;
|
||||
# padding: 10px;
|
||||
# }
|
||||
#
|
||||
# .normal-icons {
|
||||
# -gtk-icon-size: 16px;
|
||||
# }
|
||||
#
|
||||
# .large-icons {
|
||||
# -gtk-icon-size: 32px;
|
||||
# }
|
||||
#
|
||||
# scrollbar {
|
||||
# opacity: 0;
|
||||
# }
|
||||
#
|
||||
# .box-wrapper {
|
||||
# box-shadow:
|
||||
# 0 19px 38px rgba(0, 0, 0, 0.3),
|
||||
# 0 15px 12px rgba(0, 0, 0, 0.22);
|
||||
# background: @window_bg_color;
|
||||
# padding: 20px;
|
||||
# border-radius: 20px;
|
||||
# border: 1px solid darker(@accent_bg_color);
|
||||
# }
|
||||
#
|
||||
# .preview-box,
|
||||
# .elephant-hint,
|
||||
# .placeholder {
|
||||
# color: @theme_fg_color;
|
||||
# }
|
||||
#
|
||||
# .box {
|
||||
# }
|
||||
#
|
||||
# .search-container {
|
||||
# border-radius: 10px;
|
||||
# }
|
||||
#
|
||||
# .input placeholder {
|
||||
# opacity: 0.5;
|
||||
# }
|
||||
#
|
||||
# .input selection {
|
||||
# background: lighter(lighter(lighter(@window_bg_color)));
|
||||
# }
|
||||
#
|
||||
# .input {
|
||||
# caret-color: @theme_fg_color;
|
||||
# background: lighter(@window_bg_color);
|
||||
# padding: 10px;
|
||||
# color: @theme_fg_color;
|
||||
# }
|
||||
#
|
||||
# .input:focus,
|
||||
# .input:active {
|
||||
# }
|
||||
#
|
||||
# .content-container {
|
||||
# }
|
||||
#
|
||||
# .placeholder {
|
||||
# }
|
||||
#
|
||||
# .scroll {
|
||||
# }
|
||||
#
|
||||
# .list {
|
||||
# color: @theme_fg_color;
|
||||
# }
|
||||
#
|
||||
# child {
|
||||
# }
|
||||
#
|
||||
# .item-box {
|
||||
# border-radius: 10px;
|
||||
# padding: 10px;
|
||||
# }
|
||||
#
|
||||
# .item-quick-activation {
|
||||
# background: alpha(@accent_bg_color, 0.25);
|
||||
# border-radius: 5px;
|
||||
# padding: 10px;
|
||||
# }
|
||||
#
|
||||
# /* child:hover .item-box, */
|
||||
# child:selected .item-box {
|
||||
# background: alpha(@accent_bg_color, 0.25);
|
||||
# }
|
||||
#
|
||||
# .item-text-box {
|
||||
# }
|
||||
#
|
||||
# .item-subtext {
|
||||
# font-size: 12px;
|
||||
# opacity: 0.5;
|
||||
# }
|
||||
#
|
||||
# .providerlist .item-subtext {
|
||||
# font-size: unset;
|
||||
# opacity: 0.75;
|
||||
# }
|
||||
#
|
||||
# .item-image-text {
|
||||
# font-size: 28px;
|
||||
# }
|
||||
#
|
||||
# .preview {
|
||||
# border: 1px solid alpha(@accent_bg_color, 0.25);
|
||||
# /* padding: 10px; */
|
||||
# border-radius: 10px;
|
||||
# color: @theme_fg_color;
|
||||
# }
|
||||
#
|
||||
# .calc .item-text {
|
||||
# font-size: 24px;
|
||||
# }
|
||||
#
|
||||
# .calc .item-subtext {
|
||||
# }
|
||||
#
|
||||
# .symbols .item-image {
|
||||
# font-size: 24px;
|
||||
# }
|
||||
#
|
||||
# .todo.done .item-text-box {
|
||||
# opacity: 0.25;
|
||||
# }
|
||||
#
|
||||
# .todo.urgent {
|
||||
# font-size: 24px;
|
||||
# }
|
||||
#
|
||||
# .todo.active {
|
||||
# font-weight: bold;
|
||||
# }
|
||||
#
|
||||
# .bluetooth.disconnected {
|
||||
# opacity: 0.5;
|
||||
# }
|
||||
#
|
||||
# .preview .large-icons {
|
||||
# -gtk-icon-size: 64px;
|
||||
# }
|
||||
#
|
||||
# .keybinds {
|
||||
# padding-top: 10px;
|
||||
# border-top: 1px solid lighter(@window_bg_color);
|
||||
# font-size: 12px;
|
||||
# color: @theme_fg_color;
|
||||
# }
|
||||
#
|
||||
# .global-keybinds {
|
||||
# }
|
||||
#
|
||||
# .item-keybinds {
|
||||
# }
|
||||
#
|
||||
# .keybind {
|
||||
# }
|
||||
#
|
||||
# .keybind-button {
|
||||
# opacity: 0.5;
|
||||
# }
|
||||
#
|
||||
# .keybind-button:hover {
|
||||
# opacity: 0.75;
|
||||
# cursor: pointer;
|
||||
# }
|
||||
#
|
||||
# .keybind-bind {
|
||||
# text-transform: lowercase;
|
||||
# opacity: 0.35;
|
||||
# }
|
||||
#
|
||||
# .keybind-label {
|
||||
# padding: 2px 4px;
|
||||
# border-radius: 4px;
|
||||
# border: 1px solid @theme_fg_color;
|
||||
# }
|
||||
#
|
||||
# .error {
|
||||
# padding: 10px;
|
||||
# background: @error_bg_color;
|
||||
# color: @error_fg_color;
|
||||
# }
|
||||
#
|
||||
# :not(.calc).current {
|
||||
# font-style: italic;
|
||||
# }
|
||||
#
|
||||
# .preview-content.archlinuxpkgs {
|
||||
# font-family: monospace;
|
||||
# } '';
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
myConfig,
|
||||
...
|
||||
}: let
|
||||
# FIXME: waybar overlaps fullscreen display when restarting waybar
|
||||
hakase-popup-launch = pkgs.writeShellScriptBin "hakase-popup-launch" ''
|
||||
tui_name=$1
|
||||
active_popup=$(${pkgs.hyprland}/bin/hyprctl clients -j | ${pkgs.jq}/bin/jq -r '.[] | select(.class | startswith("org.hakase.")) | .class')
|
||||
|
||||
if [[ -z "''${tui_name}" ]]; then
|
||||
echo "Usage: $(basename "$0") [tui-name]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
popup_checker() {
|
||||
if [[ -z "$active_popup" ]]; then
|
||||
echo "no_popup"
|
||||
elif [[ "$active_popup" != "org.hakase.popup.''${tui_name}" ]]; then
|
||||
echo "different"
|
||||
else
|
||||
echo "same"
|
||||
fi
|
||||
}
|
||||
launch() {
|
||||
exec ${pkgs.util-linux}/bin/setsid uwsm-app -- xdg-terminal-exec --app-id=org.hakase.popup."''${tui_name}" -e "''${tui_name}"
|
||||
}
|
||||
|
||||
focus() {
|
||||
exec ${pkgs.hyprland}/bin/hyprctl dispatch focuswindow "class:org.hakase.popup.''${tui_name}"
|
||||
}
|
||||
|
||||
replace() {
|
||||
${pkgs.hyprland}/bin/hyprctl dispatch closewindow "class:''${active_popup}"
|
||||
sleep 0.3
|
||||
launch
|
||||
}
|
||||
|
||||
run() {
|
||||
local status
|
||||
status=$(popup_checker)
|
||||
|
||||
if [[ "$status" == "no_popup" ]]; then
|
||||
launch
|
||||
elif [[ "$status" == "same" ]]; then
|
||||
focus
|
||||
elif [[ "$status" == "different" ]]; then
|
||||
replace
|
||||
fi
|
||||
}
|
||||
|
||||
run
|
||||
'';
|
||||
in {
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
exec-once = [
|
||||
"uwsm app -- waybar"
|
||||
];
|
||||
|
||||
bind = [
|
||||
"SUPER, Escape, exec, hakase-popup-launch btop"
|
||||
"SUPER, N, exec, hakase-popup-launch impala"
|
||||
"SUPER, B, exec, hakase-popup-launch bluetui"
|
||||
"SUPER, T, exec, hakase-popup-launch wiremix"
|
||||
];
|
||||
|
||||
windowrulev2 = [
|
||||
# --- POPUP RULES (Wifi, BT, Audio) ---
|
||||
"float, class:^(org\.hakase\.popup\..*)$"
|
||||
"size 900 600, class:^(org\.hakase\.popup\..*)$"
|
||||
"center, class:^(org\.hakase\.popup\..*)$"
|
||||
"animation slide right, class:^(org\.hakase\.popup\..*)$"
|
||||
"dimaround, class:^(org\.hakase\.popup\..*)$"
|
||||
];
|
||||
};
|
||||
imports = [
|
||||
./style.nix
|
||||
];
|
||||
|
||||
home.packages = [
|
||||
hakase-popup-launch
|
||||
pkgs.jq
|
||||
pkgs.socat
|
||||
pkgs.util-linux
|
||||
pkgs.bluetui
|
||||
pkgs.impala
|
||||
pkgs.wiremix
|
||||
pkgs.pamixer
|
||||
];
|
||||
|
||||
programs.waybar = {
|
||||
enable = true;
|
||||
settings = {
|
||||
mainBar = {
|
||||
reload_style_on_change = true;
|
||||
layer = "top";
|
||||
position = "top";
|
||||
spacing = 0;
|
||||
height = 26;
|
||||
|
||||
modules-left = ["custom/omarchy" "hyprland/workspaces" "hyprland/workspaces#special"];
|
||||
modules-center = ["clock" "custom/update" "custom/screenrecording-indicator"];
|
||||
modules-right = [
|
||||
"group/tray-expander"
|
||||
"bluetooth"
|
||||
"network"
|
||||
"pulseaudio"
|
||||
"cpu"
|
||||
"battery"
|
||||
];
|
||||
|
||||
"hyprland/workspaces" = {
|
||||
on-click = "activate";
|
||||
show-special = false;
|
||||
all-outputs = true;
|
||||
format = "{icon}";
|
||||
format-icons = {
|
||||
"music" = "";
|
||||
"gaming" = "";
|
||||
"default" = "";
|
||||
"active" = "";
|
||||
|
||||
# Numbered workspaces 1-5
|
||||
"1" = "1";
|
||||
"2" = "2";
|
||||
"3" = "3";
|
||||
"4" = "4";
|
||||
"5" = "5";
|
||||
|
||||
# Kanji for workspaces 6-10
|
||||
"6" = "1";
|
||||
"7" = "2";
|
||||
"8" = "3";
|
||||
"9" = "4";
|
||||
"10" = "5";
|
||||
|
||||
# Dice for workspaces 11-15
|
||||
"11" = "1";
|
||||
"12" = "2";
|
||||
"13" = "3";
|
||||
"14" = "4";
|
||||
"15" = "5";
|
||||
|
||||
# Circled numbers for 16-20
|
||||
"16" = "1";
|
||||
"17" = "2";
|
||||
"18" = "3";
|
||||
"19" = "4";
|
||||
"20" = "5";
|
||||
};
|
||||
persistent-workspaces = {
|
||||
"1" = [];
|
||||
"2" = [];
|
||||
"3" = [];
|
||||
"4" = [];
|
||||
"5" = [];
|
||||
"6" = [];
|
||||
"7" = [];
|
||||
"8" = [];
|
||||
"9" = [];
|
||||
"10" = [];
|
||||
};
|
||||
};
|
||||
|
||||
"hyprland/workspaces#special" = {
|
||||
on-click = "activate";
|
||||
show-special = true;
|
||||
special-visible-only = true;
|
||||
all-outputs = true;
|
||||
ignore-workspaces = ["^([0-9]+|gaming|music|jellyfin)$"];
|
||||
format = "{icon}";
|
||||
format-icons = {
|
||||
"special:youtube" = "";
|
||||
"special:steam" = "";
|
||||
"special:custom" = "";
|
||||
"special:preload" = "";
|
||||
"special:jellyfin" = "";
|
||||
"jellyfin" = "";
|
||||
"youtube" = "";
|
||||
"steam" = "";
|
||||
"custom" = "";
|
||||
"preload" = "";
|
||||
"default" = "";
|
||||
};
|
||||
};
|
||||
|
||||
"custom/omarchy" = {
|
||||
format = "";
|
||||
on-click = "vicinae-toggle";
|
||||
on-click-right = "hyprctl dispatch overview:toggle";
|
||||
tooltip-format = "Omarchy Menu\n\nSuper + Alt + Space";
|
||||
};
|
||||
|
||||
"cpu" = {
|
||||
interval = 5;
|
||||
format = "";
|
||||
on-click = "hakase-popup-launch btop";
|
||||
on-click-right = "xdg-terminal-exec";
|
||||
};
|
||||
|
||||
"clock" = {
|
||||
format = "{:%H:%M %a %b %d}";
|
||||
format-alt = "{:L%d %B W%V %Y}";
|
||||
tooltip = false;
|
||||
on-click-right = "omarchy-launch-floating-terminal-with-presentation omarchy-tz-select";
|
||||
};
|
||||
|
||||
"network" = {
|
||||
format-icons = ["" "" "" "" ""];
|
||||
format = "{icon}";
|
||||
format-wifi = "{icon}";
|
||||
format-ethernet = "";
|
||||
format-disconnected = "";
|
||||
tooltip-format-wifi = "{essid} ({frequency} GHz)\n⇣{bandwidthDownBytes} ⇡{bandwidthUpBytes}";
|
||||
tooltip-format-ethernet = "⇣{bandwidthDownBytes} ⇡{bandwidthUpBytes}";
|
||||
tooltip-format-disconnected = "Disconnected";
|
||||
interval = 3;
|
||||
spacing = 1;
|
||||
on-click = "hakase-popup-launch impala";
|
||||
};
|
||||
|
||||
"battery" = {
|
||||
format = "{capacity}% {icon}";
|
||||
format-discharging = "{icon}";
|
||||
format-charging = "{icon}";
|
||||
format-plugged = "";
|
||||
format-icons = {
|
||||
charging = ["" "" "" "" "" "" "" "" "" ""];
|
||||
default = ["" "" "" "" "" "" "" "" "" ""];
|
||||
};
|
||||
format-full = "";
|
||||
tooltip-format-discharging = "{power:>1.0f}W↓ {capacity}%";
|
||||
tooltip-format-charging = "{power:>1.0f}W↑ {capacity}%";
|
||||
interval = 5;
|
||||
on-click = "omarchy-menu power";
|
||||
states = {
|
||||
warning = 20;
|
||||
critical = 10;
|
||||
};
|
||||
};
|
||||
|
||||
"bluetooth" = {
|
||||
format = "";
|
||||
format-disabled = "";
|
||||
format-connected = "";
|
||||
format-no-controller = "";
|
||||
tooltip-format = "Devices connected: {num_connections}";
|
||||
on-click = "hakase-popup-launch bluetui";
|
||||
};
|
||||
|
||||
"pulseaudio" = {
|
||||
format = "{icon}";
|
||||
on-click = "hakase-popup-launch wiremix ";
|
||||
on-click-right = "pamixer -t";
|
||||
tooltip-format = "Playing at {volume}%";
|
||||
scroll-step = 5;
|
||||
format-muted = "";
|
||||
format-icons = {
|
||||
default = ["" "" ""];
|
||||
};
|
||||
};
|
||||
|
||||
"group/tray-expander" = {
|
||||
orientation = "inherit";
|
||||
drawer = {
|
||||
transition-duration = 600;
|
||||
children-class = "tray-group-item";
|
||||
};
|
||||
modules = ["custom/expand-icon" "tray"];
|
||||
};
|
||||
|
||||
"custom/expand-icon" = {
|
||||
format = "";
|
||||
tooltip = false;
|
||||
};
|
||||
|
||||
"custom/screenrecording-indicator" = {
|
||||
on-click = "omarchy-cmd-screenrecord";
|
||||
exec = "$OMARCHY_PATH/default/waybar/indicators/screen-recording.sh";
|
||||
signal = 8;
|
||||
return-type = "json";
|
||||
};
|
||||
|
||||
"tray" = {
|
||||
icon-size = 12;
|
||||
spacing = 17;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
{
|
||||
config,
|
||||
myConfig,
|
||||
...
|
||||
}: {
|
||||
programs.waybar = {
|
||||
style = ''
|
||||
@import "matugen.css";
|
||||
* {
|
||||
background-color: @background;
|
||||
color: @on_surface;
|
||||
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
min-height: 0;
|
||||
font-family: '${myConfig.font.monospace}';
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.modules-left {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.modules-right {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
#workspaces button {
|
||||
all: initial;
|
||||
padding: 0 6px;
|
||||
margin: 0 1.5px;
|
||||
min-width: 9px;
|
||||
}
|
||||
|
||||
#workspaces button.empty {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* Add spacing separator every 5 workspaces */
|
||||
#workspaces button:nth-child(5),
|
||||
#workspaces button:nth-child(10),
|
||||
#workspaces button:nth-child(15) {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
/* Separator between normal and special workspaces */
|
||||
#workspaces.special {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
#cpu,
|
||||
#battery,
|
||||
#pulseaudio,
|
||||
#custom-omarchy,
|
||||
#custom-screenrecording-indicator,
|
||||
#custom-update {
|
||||
min-width: 12px;
|
||||
margin: 0 7.5px;
|
||||
}
|
||||
|
||||
#tray {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
#bluetooth {
|
||||
margin-right: 17px;
|
||||
}
|
||||
|
||||
#network {
|
||||
margin-right: 13px;
|
||||
}
|
||||
|
||||
#custom-expand-icon {
|
||||
margin-right: 18px;
|
||||
}
|
||||
|
||||
tooltip {
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
#custom-update {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
#clock {
|
||||
margin-left: 8.75px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
#custom-screenrecording-indicator {
|
||||
min-width: 12px;
|
||||
margin-left: 8.75px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
#custom-screenrecording-indicator.active {
|
||||
color: @on_secondary;
|
||||
}
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
programs.wireshark.enable = true;
|
||||
# dumpcap.enable = true;
|
||||
usbmon.enable = true;
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
{
|
||||
pkgs,
|
||||
myConfig,
|
||||
...
|
||||
}: let
|
||||
# Yazi wrapper for xdg-desktop-portal-termfilechooser
|
||||
# TODO: rewrite in the future
|
||||
yaziWrapper = pkgs.writeShellScript "yazi-wrapper.sh" ''
|
||||
if [[ "$6" == "1" ]]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
multiple="$1"
|
||||
directory="$2"
|
||||
save="$3"
|
||||
path="$4"
|
||||
out="$5"
|
||||
|
||||
termcmd="${pkgs.util-linux}/bin/setsid uwsm-app -- xdg-terminal-exec --app-id=org.hakase.popup.yazi -e"
|
||||
|
||||
cleanup() {
|
||||
if [ -f "$tmpfile" ]; then
|
||||
rm "$tmpfile" || :
|
||||
fi
|
||||
if [ "$save" = "1" ] && [ ! -s "$out" ]; then
|
||||
rm "$path" || :
|
||||
fi
|
||||
}
|
||||
|
||||
trap cleanup EXIT HUP INT QUIT ABRT TERM
|
||||
|
||||
if [ "$save" = "1" ]; then
|
||||
tmpfile=$(mktemp)
|
||||
|
||||
printf '%s' 'xdg-desktop-portal-termfilechooser saving files tutorial
|
||||
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!!! === WARNING! === !!!
|
||||
!!! The contents of *whatever* file you open last in !!!
|
||||
!!! yazi will be *overwritten*! !!!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
Instructions:
|
||||
1) Move this file wherever you want.
|
||||
2) Rename the file if needed.
|
||||
3) Confirm your selection by opening the file, for
|
||||
example by pressing <Enter>.
|
||||
|
||||
Notes:
|
||||
1) This file is provided for your convenience. You can
|
||||
only choose this placeholder file otherwise the save operation aborted.
|
||||
2) If you quit yazi without opening a file, this file
|
||||
will be removed and the save operation aborted.
|
||||
' >"$path"
|
||||
|
||||
$termcmd ${pkgs.yazi}/bin/yazi --chooser-file="$tmpfile" "$path"
|
||||
elif [ "$directory" = "1" ]; then
|
||||
$termcmd ${pkgs.yazi}/bin/yazi --cwd-file="$out" "$path"
|
||||
elif [ "$multiple" = "1" ]; then
|
||||
$termcmd ${pkgs.yazi}/bin/yazi --chooser-file="$out" "$path"
|
||||
else
|
||||
$termcmd ${pkgs.yazi}/bin/yazi --chooser-file="$out" "$path"
|
||||
fi
|
||||
|
||||
# Handle save file case
|
||||
if [ "$save" = "1" ] && [ -s "$tmpfile" ]; then
|
||||
selected_file=$(head -n 1 "$tmpfile")
|
||||
if [ -f "$selected_file" ] && grep -qi "^xdg-desktop-portal-termfilechooser saving files tutorial" "$selected_file"; then
|
||||
echo "$selected_file" >"$out"
|
||||
fi
|
||||
fi
|
||||
'';
|
||||
in {
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
bindd = [
|
||||
"SUPER, X, Open File Manager, exec, uwsm app -- yazi"
|
||||
];
|
||||
};
|
||||
|
||||
programs.yazi = {
|
||||
enable = true;
|
||||
enableFishIntegration = true;
|
||||
settings = {
|
||||
manager = {
|
||||
show_hidden = false;
|
||||
sort_by = "mtime";
|
||||
sort_reverse = true;
|
||||
sort_dir_first = false;
|
||||
linemode = "size";
|
||||
mouse_events = ["click" "scroll" "touch" "move" "drag"];
|
||||
};
|
||||
tasks = {
|
||||
image_bound = [10000 10000];
|
||||
};
|
||||
opener = {
|
||||
anki = [
|
||||
{
|
||||
run = "anki \"$@\"";
|
||||
desc = "Open with Anki";
|
||||
}
|
||||
];
|
||||
pdf = [
|
||||
{
|
||||
run = "zathura \"$@\"";
|
||||
desc = "Open with Zathura";
|
||||
}
|
||||
{
|
||||
run = "firefox \"$@\"";
|
||||
desc = "Open with Firefox";
|
||||
}
|
||||
];
|
||||
};
|
||||
open = {
|
||||
prepend_rules = [
|
||||
{
|
||||
name = "*.{apkg,colpkg}";
|
||||
use = "anki";
|
||||
}
|
||||
{
|
||||
mime = "application/pdf";
|
||||
use = "pdf";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Portal packages need to be in user profile for proper path resolution
|
||||
home.packages = [
|
||||
pkgs.xdg-desktop-portal-hyprland
|
||||
pkgs.xdg-desktop-portal-gtk
|
||||
pkgs.xdg-desktop-portal-termfilechooser
|
||||
];
|
||||
|
||||
# xdg-desktop-portal-termfilechooser configuration
|
||||
xdg.configFile."xdg-desktop-portal-termfilechooser/config".text = ''
|
||||
[filechooser]
|
||||
cmd=${yaziWrapper}
|
||||
default_dir=$HOME/Downloads
|
||||
'';
|
||||
|
||||
# Portal routing configuration - use termfilechooser for file dialogs
|
||||
xdg.configFile."xdg-desktop-portal/portals.conf".text = ''
|
||||
[preferred]
|
||||
default=hyprland;gtk
|
||||
org.freedesktop.impl.portal.FileChooser=termfilechooser
|
||||
'';
|
||||
|
||||
xdg.mimeApps = {
|
||||
enable = true;
|
||||
defaultApplications = {
|
||||
"inode/directory" = "yazi.desktop";
|
||||
};
|
||||
};
|
||||
|
||||
wayland.windowManager.hyprland.settings.windowrulev2 = [
|
||||
# File picker yazi - floating, centered, smaller size
|
||||
"float, class:^(org\\.hakase\\.popup\\.yazi)$"
|
||||
"size 60% 70%, class:^(org\\.hakase\\.popup\\.yazi)$"
|
||||
"center, class:^(org\\.hakase\\.popup\\.yazi)$"
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
home.packages = with pkgs; [
|
||||
ocrmypdf
|
||||
];
|
||||
programs.zathura = {
|
||||
enable = true;
|
||||
options = {
|
||||
selection-clipboard = "clipboard";
|
||||
adjust-open = "best-fit";
|
||||
pages-per-row = 1;
|
||||
scroll-page-aware = "true";
|
||||
scroll-full-overlap = "0.01";
|
||||
scroll-step = 100;
|
||||
zoom-min = 10;
|
||||
recolor = true;
|
||||
recolor-keephue = true;
|
||||
};
|
||||
extraConfig = "include ${config.home.homeDirectory}/.config/zathura/zathura-matugen";
|
||||
};
|
||||
|
||||
home.activation.createZathuraMatugen = lib.hm.dag.entryAfter ["writeBoundary"] ''
|
||||
if [ ! -f "${config.home.homeDirectory}/.config/zathura/zathura-matugen" ]; then
|
||||
touch "${config.home.homeDirectory}/.config/zathura/zathura-matugen"
|
||||
fi
|
||||
'';
|
||||
|
||||
xdg.mimeApps = {
|
||||
enable = true;
|
||||
defaultApplications = {
|
||||
"application/pdf" = "org.pwmt.zathura.desktop";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
programs.zoxide = {
|
||||
enable = true;
|
||||
enableFishIntegration = true;
|
||||
options = [
|
||||
"--cmd cd"
|
||||
];
|
||||
};
|
||||
}
|
||||
|
After Width: | Height: | Size: 282 KiB |
|
After Width: | Height: | Size: 4.3 MiB |
@@ -0,0 +1,6 @@
|
||||
██╗ ██╗ █████╗ ██╗ ██╗ █████╗ ███████╗███████╗
|
||||
██║ ██║██╔══██╗██║ ██╔╝██╔══██╗██╔════╝██╔════╝
|
||||
███████║███████║█████╔╝ ███████║███████╗█████╗
|
||||
██╔══██║██╔══██║██╔═██╗ ██╔══██║╚════██║██╔══╝
|
||||
██║ ██║██║ ██║██║ ██╗██║ ██║███████║███████╗
|
||||
╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝
|
||||
|
After Width: | Height: | Size: 476 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 826 KiB |
|
After Width: | Height: | Size: 3.2 MiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 2.6 MiB |