mirror of
https://github.com/nix-community/home-manager.git
synced 2026-01-11 17:39:37 +08:00
Compare commits
1348 Commits
release-17
...
lieer-notm
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1eb2dcf3a9 | ||
|
|
c12897e8e1 | ||
|
|
4fd4066d2f | ||
|
|
7fcfd9b565 | ||
|
|
3a16ebdf72 | ||
|
|
e5a260a569 | ||
|
|
33edf558a0 | ||
|
|
cc60c22c69 | ||
|
|
25a6a6d298 | ||
|
|
6e3d93d7cc | ||
|
|
ad04237d51 | ||
|
|
447ed0fbcb | ||
|
|
90223cf3eb | ||
|
|
cbf0667037 | ||
|
|
c1761366b5 | ||
|
|
7b30fc9922 | ||
|
|
fedfd430f9 | ||
|
|
ddcd476603 | ||
|
|
f30b62a74d | ||
|
|
f9b5172d95 | ||
|
|
de1fa8defb | ||
|
|
6245dd11cf | ||
|
|
ffbc3819e4 | ||
|
|
920ea74afe | ||
|
|
b42d987ad9 | ||
|
|
07f6c6481e | ||
|
|
1ee1835a3e | ||
|
|
42bb553544 | ||
|
|
19c7d4e29f | ||
|
|
a4e146693e | ||
|
|
040ea28e44 | ||
|
|
57a7e5e2c5 | ||
|
|
5fbb33cff5 | ||
|
|
abc9d96d19 | ||
|
|
73559e0dbc | ||
|
|
0e2dc4be30 | ||
|
|
39e4991856 | ||
|
|
69e2693342 | ||
|
|
ddee030dc7 | ||
|
|
e72e241d7a | ||
|
|
9068ff292c | ||
|
|
f45c7000d5 | ||
|
|
aa479b0124 | ||
|
|
3327cbe1f9 | ||
|
|
fb9bf032fb | ||
|
|
e7b1491fb8 | ||
|
|
0933fb8765 | ||
|
|
7582090eb0 | ||
|
|
21952f1cab | ||
|
|
029767ca63 | ||
|
|
aa9affb53f | ||
|
|
82d6ba7003 | ||
|
|
eb3a0342a8 | ||
|
|
2b7a73071a | ||
|
|
da92360208 | ||
|
|
55030c8302 | ||
|
|
2e795f3efd | ||
|
|
1ee1d01daa | ||
|
|
87e2ec341b | ||
|
|
e6f2687a83 | ||
|
|
b220d5c446 | ||
|
|
88e05a5472 | ||
|
|
d8dd2a09b0 | ||
|
|
ef4370bedc | ||
|
|
bdee1be7b3 | ||
|
|
dd6ee694df | ||
|
|
6dfa9ef85c | ||
|
|
fc87ac92af | ||
|
|
d420287583 | ||
|
|
46a750f94f | ||
|
|
63d5d28db6 | ||
|
|
22ecd0e568 | ||
|
|
3f2f7f8efa | ||
|
|
9dad146639 | ||
|
|
bbb6d30001 | ||
|
|
0fa2b16a07 | ||
|
|
df7d81b0b3 | ||
|
|
98d030f723 | ||
|
|
7313258b45 | ||
|
|
db88b625f9 | ||
|
|
7de0d07dd9 | ||
|
|
6b15b03898 | ||
|
|
c137866bd7 | ||
|
|
3d634914ce | ||
|
|
e44faef21c | ||
|
|
6f7074d21d | ||
|
|
9a12cd7e81 | ||
|
|
08fc1586c0 | ||
|
|
4e86d65aee | ||
|
|
2c0e3f61da | ||
|
|
5280360d6c | ||
|
|
c33b1777b6 | ||
|
|
b0c8727286 | ||
|
|
6f5fa6350d | ||
|
|
9d680ec662 | ||
|
|
7e80e034cc | ||
|
|
8f24ed4c7f | ||
|
|
3fe2a57b95 | ||
|
|
8127799f79 | ||
|
|
4b772fd698 | ||
|
|
65d0e2d241 | ||
|
|
d62bdaf938 | ||
|
|
45e3b0ce0e | ||
|
|
cc89be5a30 | ||
|
|
e8358125d9 | ||
|
|
cb1ed0d2f3 | ||
|
|
32371301d3 | ||
|
|
cf5dad76c1 | ||
|
|
a361541c10 | ||
|
|
b9597e5774 | ||
|
|
68dfc86173 | ||
|
|
73506f947c | ||
|
|
f0e6396b78 | ||
|
|
6acc6bc651 | ||
|
|
f6fd7e3fa4 | ||
|
|
05448dcedb | ||
|
|
374649a15b | ||
|
|
118b36bf45 | ||
|
|
3e218f2600 | ||
|
|
f4b5ae026c | ||
|
|
9d53afb709 | ||
|
|
4dedfcfd95 | ||
|
|
8e0c1c55fb | ||
|
|
99f0074362 | ||
|
|
5263fe4594 | ||
|
|
cd86c2638b | ||
|
|
bcbf09a202 | ||
|
|
ca7fd5a643 | ||
|
|
3627ec4de5 | ||
|
|
2901044520 | ||
|
|
cb136f37c7 | ||
|
|
76de0632ac | ||
|
|
8b3fca4ec5 | ||
|
|
2b1892e646 | ||
|
|
a1162e04b3 | ||
|
|
e87bccabc3 | ||
|
|
1a7f190cb9 | ||
|
|
66a68b4a58 | ||
|
|
6dc8de259a | ||
|
|
708cb61e82 | ||
|
|
b6ed605d4a | ||
|
|
6739d8bb50 | ||
|
|
4f0b0d78af | ||
|
|
9d775bad07 | ||
|
|
e6a58a7e71 | ||
|
|
e3828769e8 | ||
|
|
275d1b5212 | ||
|
|
aaa5329d39 | ||
|
|
005ea6cc18 | ||
|
|
0654364426 | ||
|
|
0027b0e76b | ||
|
|
33407189c1 | ||
|
|
44f9d68d8c | ||
|
|
c1faa848c5 | ||
|
|
c6263347de | ||
|
|
a3a0f1289a | ||
|
|
7b6ebf2785 | ||
|
|
6dc68b1d16 | ||
|
|
99b75f99df | ||
|
|
964f698095 | ||
|
|
4f20ee61c2 | ||
|
|
9e01441c5c | ||
|
|
9fe15dc83b | ||
|
|
b9b8a42fda | ||
|
|
b04aa56503 | ||
|
|
cde1d33e61 | ||
|
|
b3fdbfdf42 | ||
|
|
f3372bf982 | ||
|
|
234de0270a | ||
|
|
9c14bbe988 | ||
|
|
7c3c64208e | ||
|
|
b5e7817de2 | ||
|
|
fe849640ad | ||
|
|
fd79015c0f | ||
|
|
4cc1b77c3f | ||
|
|
9e9d8ffc7c | ||
|
|
faca77d77d | ||
|
|
ef72617c4a | ||
|
|
249e31b656 | ||
|
|
0261950395 | ||
|
|
1066e01707 | ||
|
|
61e63c10dc | ||
|
|
5125fc0a47 | ||
|
|
cabf9ddd98 | ||
|
|
612afee126 | ||
|
|
072a6ea333 | ||
|
|
a98ec6ec15 | ||
|
|
c8746fb588 | ||
|
|
99fbae0ec5 | ||
|
|
b5291e995f | ||
|
|
28eb093a1e | ||
|
|
abaebf3b34 | ||
|
|
9bf1f40af1 | ||
|
|
22a3a5651d | ||
|
|
308ee310de | ||
|
|
0778a80ee0 | ||
|
|
10df7a7eee | ||
|
|
9cf5f764e1 | ||
|
|
014d8deb60 | ||
|
|
1c4ced745c | ||
|
|
731959ef0e | ||
|
|
18429f1d1d | ||
|
|
77913ff17e | ||
|
|
dc5239b5ce | ||
|
|
c5e47e25a6 | ||
|
|
e7d5531cfa | ||
|
|
aecd4acfb4 | ||
|
|
18a05a9604 | ||
|
|
7339784e07 | ||
|
|
0e9b6e6dc9 | ||
|
|
fc5619764e | ||
|
|
57518cd0bf | ||
|
|
b584745506 | ||
|
|
473d9acdad | ||
|
|
8537920706 | ||
|
|
7e5fee4268 | ||
|
|
0006da1381 | ||
|
|
9ff2188c5d | ||
|
|
da6077a899 | ||
|
|
41147ae09a | ||
|
|
6fed10a09a | ||
|
|
f0fc2a8702 | ||
|
|
521a808151 | ||
|
|
abfb4cde51 | ||
|
|
43ab2f40b9 | ||
|
|
690d93c22a | ||
|
|
8a160f01ab | ||
|
|
a6a3abb295 | ||
|
|
84bcce3c25 | ||
|
|
96d7de6db1 | ||
|
|
9b1b55ba02 | ||
|
|
b3498cccb3 | ||
|
|
92c682cd10 | ||
|
|
472ca211ca | ||
|
|
812b64d4d3 | ||
|
|
605a8fc92e | ||
|
|
b819d2cc41 | ||
|
|
1f04af74f2 | ||
|
|
249650a07e | ||
|
|
4ebb7d1715 | ||
|
|
1a6d6b8ace | ||
|
|
f146620897 | ||
|
|
41b1af808f | ||
|
|
182454fe6b | ||
|
|
a063b73d5c | ||
|
|
d3aee544b6 | ||
|
|
bd4c2b0651 | ||
|
|
1f34c048b3 | ||
|
|
bfc66df13d | ||
|
|
1ed8e7ef98 | ||
|
|
e6e49ad73c | ||
|
|
0399839271 | ||
|
|
4b702bf6b7 | ||
|
|
4fe5afa755 | ||
|
|
209fb62d49 | ||
|
|
6cf6b587b5 | ||
|
|
a79d31fcfd | ||
|
|
0869e23700 | ||
|
|
625b92cbba | ||
|
|
9854342b9f | ||
|
|
a3dd580adc | ||
|
|
2bcd96928e | ||
|
|
2c6a023744 | ||
|
|
9a473b693a | ||
|
|
f4f9f1a618 | ||
|
|
2a54c353a9 | ||
|
|
96e2f1bdf0 | ||
|
|
3886f8db33 | ||
|
|
baea46c5ac | ||
|
|
fceef469c2 | ||
|
|
ae8f432a75 | ||
|
|
e1fbb74b41 | ||
|
|
d1f4d1514d | ||
|
|
861690ff29 | ||
|
|
223e3c38a1 | ||
|
|
9c0fe3957b | ||
|
|
152769aed9 | ||
|
|
dbf6b2d2ab | ||
|
|
f119d4d142 | ||
|
|
79a2320fd0 | ||
|
|
bb6eb9b13e | ||
|
|
2e7935767f | ||
|
|
89adfc9f01 | ||
|
|
7b73f84071 | ||
|
|
5cd7865c6c | ||
|
|
3f1be69359 | ||
|
|
83301ca787 | ||
|
|
8ad5580021 | ||
|
|
e2e8b7371d | ||
|
|
4bd0ca2cd7 | ||
|
|
5c639ff68a | ||
|
|
a49ce0e9ed | ||
|
|
1a8ab9d9de | ||
|
|
e0fb488e57 | ||
|
|
05565a0145 | ||
|
|
5f189acce4 | ||
|
|
7dc322c1eb | ||
|
|
8736190743 | ||
|
|
7f7348b470 | ||
|
|
58716b7541 | ||
|
|
600f39f966 | ||
|
|
a94c8b072e | ||
|
|
5a15f3833d | ||
|
|
54b69d2ef8 | ||
|
|
8f2342e13a | ||
|
|
8ab1139891 | ||
|
|
1f174f6681 | ||
|
|
bf7297d55c | ||
|
|
ad4f33cfc4 | ||
|
|
ecb93ab9ae | ||
|
|
dc227b579d | ||
|
|
7682eb88c4 | ||
|
|
b0e8a1569e | ||
|
|
1b210e7143 | ||
|
|
bb567e20b3 | ||
|
|
507e446475 | ||
|
|
478022afad | ||
|
|
edc3bede6e | ||
|
|
21fbc5e5ad | ||
|
|
43ef16c3e1 | ||
|
|
561b3d5650 | ||
|
|
a3cb63265d | ||
|
|
4ba9cedd68 | ||
|
|
6f683d9726 | ||
|
|
2209d3cb51 | ||
|
|
3815248786 | ||
|
|
02c1f8d416 | ||
|
|
c378c1cbcd | ||
|
|
89be0943e1 | ||
|
|
abcddfe090 | ||
|
|
5a97bf30d4 | ||
|
|
b33802ca7f | ||
|
|
575cd4b8ba | ||
|
|
68b931aef8 | ||
|
|
2dbe637478 | ||
|
|
479274775f | ||
|
|
ba91ac5948 | ||
|
|
cca5161289 | ||
|
|
354344d971 | ||
|
|
248dc17394 | ||
|
|
410d2febbb | ||
|
|
42fd47b246 | ||
|
|
46cd37abc9 | ||
|
|
b2a7d24770 | ||
|
|
3b33862b04 | ||
|
|
85748171ec | ||
|
|
0ee5c9536b | ||
|
|
ca6fcc92a1 | ||
|
|
8e8210b441 | ||
|
|
a21c97d011 | ||
|
|
dd50dc4c13 | ||
|
|
b567d27394 | ||
|
|
d64fff1fe0 | ||
|
|
c8b73e415a | ||
|
|
728c3eba67 | ||
|
|
a505bb5253 | ||
|
|
8bbefa77f7 | ||
|
|
3a80ece9fa | ||
|
|
fe59b5bbc7 | ||
|
|
8af92f844f | ||
|
|
f36c8a09e6 | ||
|
|
0e2858af94 | ||
|
|
5ba71ef91f | ||
|
|
a957e2dc6b | ||
|
|
99a97c917a | ||
|
|
09304026ae | ||
|
|
b95ad63201 | ||
|
|
2ed978eb79 | ||
|
|
31ed6f1604 | ||
|
|
ac6235e53d | ||
|
|
f90b86b577 | ||
|
|
1c71bd1242 | ||
|
|
a0d9a58616 | ||
|
|
d99f54b51b | ||
|
|
4d49cee194 | ||
|
|
dcbe0f2a31 | ||
|
|
cc48e15f28 | ||
|
|
a43e7112e5 | ||
|
|
6c7a031367 | ||
|
|
645149d77b | ||
|
|
9ec9f004e1 | ||
|
|
0fe984d575 | ||
|
|
69f8e47e9e | ||
|
|
db6e261794 | ||
|
|
5cfc9fed79 | ||
|
|
40b1c5c448 | ||
|
|
e9945ee6ee | ||
|
|
cca024da2b | ||
|
|
1ec45b11ab | ||
|
|
4ae188bfc7 | ||
|
|
7f4053084c | ||
|
|
37202a1b70 | ||
|
|
b886cbea0b | ||
|
|
9f396fddc6 | ||
|
|
2434984336 | ||
|
|
1afa5e257b | ||
|
|
cba7b6ee6e | ||
|
|
03b4f81679 | ||
|
|
1dd226fde7 | ||
|
|
ded327b9fc | ||
|
|
ecc1f2310c | ||
|
|
866d7d5152 | ||
|
|
91551c09d4 | ||
|
|
70f7c9f355 | ||
|
|
10673bff4c | ||
|
|
642d9ffe24 | ||
|
|
8b82f52e75 | ||
|
|
a7cdfaa325 | ||
|
|
a6037a9eb8 | ||
|
|
23220d43f3 | ||
|
|
ad8b644de1 | ||
|
|
95b95b1407 | ||
|
|
cfaf213980 | ||
|
|
5baa0c300f | ||
|
|
2d88cbe496 | ||
|
|
8369624512 | ||
|
|
ee1c40e5c5 | ||
|
|
2f2a4396c6 | ||
|
|
cb17f1ede2 | ||
|
|
42e4eef749 | ||
|
|
7613fd12ec | ||
|
|
f735fac91b | ||
|
|
f0710115c5 | ||
|
|
8c920682e6 | ||
|
|
9905ab5087 | ||
|
|
b3bbc8b769 | ||
|
|
3a5cd90631 | ||
|
|
3e3de8cee2 | ||
|
|
687395ebda | ||
|
|
e5325c2274 | ||
|
|
3461ceebc0 | ||
|
|
133badb297 | ||
|
|
86ccd8fecb | ||
|
|
f6afd95ef8 | ||
|
|
022228e0aa | ||
|
|
8ad4bd6c1b | ||
|
|
9f223e98b7 | ||
|
|
2102b4e7b3 | ||
|
|
ebdfa06685 | ||
|
|
41094aa3c7 | ||
|
|
09abc29b73 | ||
|
|
5b7b9821e0 | ||
|
|
ee18288eeb | ||
|
|
f856da6690 | ||
|
|
5cdbfc9064 | ||
|
|
068ff76a10 | ||
|
|
b7737f1732 | ||
|
|
d06bcf4c97 | ||
|
|
dd538c2969 | ||
|
|
f56c4187a4 | ||
|
|
1fd874b7ea | ||
|
|
5ff245790d | ||
|
|
1cfc0a3203 | ||
|
|
a128e35927 | ||
|
|
dd93c300bb | ||
|
|
14f83a46d0 | ||
|
|
5969551a5c | ||
|
|
7fa890462d | ||
|
|
78a0bbb38b | ||
|
|
e2414c4a4f | ||
|
|
d11803d7b4 | ||
|
|
19dd9866da | ||
|
|
f080f29292 | ||
|
|
8571e568e0 | ||
|
|
fe145b12cd | ||
|
|
0f11a79e02 | ||
|
|
ac9e44a831 | ||
|
|
3673107bc4 | ||
|
|
b9d4f55228 | ||
|
|
37694e9f51 | ||
|
|
2cd168467e | ||
|
|
cc386e4b3b | ||
|
|
2681568f2b | ||
|
|
5c1e7349bb | ||
|
|
9f46d516fa | ||
|
|
60a939bd01 | ||
|
|
0056a5aea1 | ||
|
|
b36d3e0261 | ||
|
|
efbe1383e6 | ||
|
|
c7b43786ad | ||
|
|
a11cf1decd | ||
|
|
9a1feb5b10 | ||
|
|
71c7aaee83 | ||
|
|
faa2945606 | ||
|
|
1a4c10e950 | ||
|
|
f3fbb50b68 | ||
|
|
a6657d6b21 | ||
|
|
0a1ce53990 | ||
|
|
2678fb3441 | ||
|
|
6fc6c736f9 | ||
|
|
28401ddd91 | ||
|
|
7bd043e9ee | ||
|
|
acf106ced0 | ||
|
|
2f726bbd1c | ||
|
|
02d6040003 | ||
|
|
2fcdf3df34 | ||
|
|
aedde6dcde | ||
|
|
ef148ab3cb | ||
|
|
03b622b356 | ||
|
|
9ab59dd6ac | ||
|
|
9ab4e70d17 | ||
|
|
91c7059d98 | ||
|
|
d90ae6dffa | ||
|
|
9ab0d2305c | ||
|
|
9bddef74df | ||
|
|
4e50809c78 | ||
|
|
7f748f27bc | ||
|
|
543118ac70 | ||
|
|
57bd27b3e7 | ||
|
|
5ca224f75b | ||
|
|
89239d554d | ||
|
|
a08dabf015 | ||
|
|
9a258edc10 | ||
|
|
111011b2c2 | ||
|
|
108259925a | ||
|
|
639f6fea8c | ||
|
|
f5b24635b6 | ||
|
|
0522c7c1f6 | ||
|
|
2f51b9e418 | ||
|
|
4f532948f7 | ||
|
|
0740c257b1 | ||
|
|
490f5fc585 | ||
|
|
642bd67126 | ||
|
|
4833a8b532 | ||
|
|
d45e1c4adc | ||
|
|
3de8102e7f | ||
|
|
665766f8bb | ||
|
|
2eb1cb077d | ||
|
|
c22f3e1d29 | ||
|
|
b18d302d44 | ||
|
|
5be9aa417a | ||
|
|
7a3e2cc063 | ||
|
|
e1153f4d2e | ||
|
|
7b7499dd70 | ||
|
|
f0fe18cd22 | ||
|
|
f487b527ec | ||
|
|
6cc4fd6ede | ||
|
|
115e76ae12 | ||
|
|
a4a07ba996 | ||
|
|
70af3b126a | ||
|
|
45abf3d38a | ||
|
|
9799d3de2d | ||
|
|
a591e8f9e4 | ||
|
|
de8033747c | ||
|
|
fba87f8998 | ||
|
|
d8d5f85ab7 | ||
|
|
b4e8d9869f | ||
|
|
b270fcef2f | ||
|
|
244d795325 | ||
|
|
e5fb259872 | ||
|
|
ba097beb17 | ||
|
|
1397570eea | ||
|
|
57ede1369f | ||
|
|
95c8007b8f | ||
|
|
805d82e1be | ||
|
|
6e4b9af080 | ||
|
|
c8323a0bf1 | ||
|
|
4b04050953 | ||
|
|
f65510b1d1 | ||
|
|
7f87329fca | ||
|
|
6c127efb2d | ||
|
|
b053dc8697 | ||
|
|
bff499113e | ||
|
|
ee01d24a45 | ||
|
|
e9beef31eb | ||
|
|
cff9ee7cce | ||
|
|
07dc3e5425 | ||
|
|
e857249d86 | ||
|
|
8ace1ab1b0 | ||
|
|
00e26ceffe | ||
|
|
4ad3fe78f9 | ||
|
|
297ed97166 | ||
|
|
0fce533e70 | ||
|
|
3a3657b107 | ||
|
|
d677556e62 | ||
|
|
1b7b1bc294 | ||
|
|
ef6674d1d1 | ||
|
|
e70912df26 | ||
|
|
0bb2d87cfd | ||
|
|
ebf1df58da | ||
|
|
7c30831e8f | ||
|
|
df4db50632 | ||
|
|
54f367b119 | ||
|
|
f66cc1b851 | ||
|
|
a0ab0b16fe | ||
|
|
5992c1b469 | ||
|
|
8d14ffbe88 | ||
|
|
a5d3d6f665 | ||
|
|
a12a8f7977 | ||
|
|
0f1c9f25cf | ||
|
|
8abaa025ec | ||
|
|
621c98f15a | ||
|
|
bcfc52cb85 | ||
|
|
5c9ec0d8e9 | ||
|
|
284b8d94d4 | ||
|
|
bb5dea02b9 | ||
|
|
711109d468 | ||
|
|
ed9a6e34ad | ||
|
|
571989f564 | ||
|
|
fdd65e5fad | ||
|
|
7c2532d9f9 | ||
|
|
94d183eaaa | ||
|
|
9d09738e4d | ||
|
|
ef11164c0c | ||
|
|
34dc4a5e03 | ||
|
|
0e9b7aab3c | ||
|
|
9781f3766d | ||
|
|
9e716025b6 | ||
|
|
eee6ae33e8 | ||
|
|
b1dd373f5a | ||
|
|
286dd9b308 | ||
|
|
595150be86 | ||
|
|
08094f3cc2 | ||
|
|
24dbac8da7 | ||
|
|
18dc4153c7 | ||
|
|
4505710565 | ||
|
|
05dabb7239 | ||
|
|
49852220f9 | ||
|
|
6b6f759e7a | ||
|
|
149c0593ab | ||
|
|
26defdf205 | ||
|
|
5161dd3b2e | ||
|
|
a93d01fb4d | ||
|
|
797c77a00a | ||
|
|
a177d0282f | ||
|
|
1b987952b5 | ||
|
|
410f573226 | ||
|
|
024d1aa227 | ||
|
|
b1d8c0f9c3 | ||
|
|
90bf989002 | ||
|
|
79c16b9a90 | ||
|
|
83018ac54a | ||
|
|
ad52dbe044 | ||
|
|
8bddc1adab | ||
|
|
e8dbc35613 | ||
|
|
3d546e0d01 | ||
|
|
a5999a62cd | ||
|
|
761b3d0c12 | ||
|
|
bdb4cf6c59 | ||
|
|
7205d3b2d2 | ||
|
|
bb5c29107e | ||
|
|
3f45630180 | ||
|
|
51581b7e43 | ||
|
|
b0544c8cde | ||
|
|
e347e932af | ||
|
|
0dfa1eef25 | ||
|
|
aa5ba177cc | ||
|
|
41f918499b | ||
|
|
d3e316eec5 | ||
|
|
45ec65e1cc | ||
|
|
05d91c5f50 | ||
|
|
d6b36f12ff | ||
|
|
824d31a21c | ||
|
|
0083087e01 | ||
|
|
1923ac3358 | ||
|
|
698d0f0a44 | ||
|
|
ec0459e139 | ||
|
|
d5e73c39fc | ||
|
|
a144c723a1 | ||
|
|
a28614e65d | ||
|
|
8ab1d22a82 | ||
|
|
b6289f7022 | ||
|
|
875eea1330 | ||
|
|
7c76ae1814 | ||
|
|
c142e5264d | ||
|
|
5d7eabb93f | ||
|
|
f1146a1fef | ||
|
|
55b71223d4 | ||
|
|
db86bd6c01 | ||
|
|
13fa61744c | ||
|
|
8fe4e0879c | ||
|
|
6bec9547c6 | ||
|
|
bfc28cacbe | ||
|
|
b2a787ca69 | ||
|
|
eb1b86a5ec | ||
|
|
7159c293af | ||
|
|
eb0ccf7286 | ||
|
|
35752e07fa | ||
|
|
57925c50bf | ||
|
|
0e871b490e | ||
|
|
ed4f66185f | ||
|
|
3d645c0ce1 | ||
|
|
8830b8d082 | ||
|
|
73641e492c | ||
|
|
c2429ca0cf | ||
|
|
7834ffbbf1 | ||
|
|
fa82ced414 | ||
|
|
9cc30b18f7 | ||
|
|
db0dfb4b08 | ||
|
|
5eed33ef08 | ||
|
|
31ae1bc2ff | ||
|
|
6932e6330e | ||
|
|
a124dae35a | ||
|
|
5203340b64 | ||
|
|
ed0e40dee8 | ||
|
|
8b759c24e6 | ||
|
|
1499b85ac6 | ||
|
|
fcdab6a62d | ||
|
|
5c94538c7d | ||
|
|
2eae9daae7 | ||
|
|
55c962fda2 | ||
|
|
eb7f39f0aa | ||
|
|
7310cfc557 | ||
|
|
42ad0effdd | ||
|
|
bce63e4dff | ||
|
|
9302523d34 | ||
|
|
a9ecef1fa9 | ||
|
|
e59b8b0c37 | ||
|
|
3743e8995a | ||
|
|
4c9b40ca0e | ||
|
|
d625186ce5 | ||
|
|
caf3349f01 | ||
|
|
6239ce20af | ||
|
|
54de0e1d79 | ||
|
|
056443ccbd | ||
|
|
7d68c46feb | ||
|
|
734128930f | ||
|
|
cc0cd538e6 | ||
|
|
ca4f22be85 | ||
|
|
c3520bfa52 | ||
|
|
2029e104d4 | ||
|
|
7c76f4a71f | ||
|
|
95382060eb | ||
|
|
472d7731d6 | ||
|
|
28f2dd612e | ||
|
|
8467e7e10a | ||
|
|
8f7cd53204 | ||
|
|
68fe8623ad | ||
|
|
8243cc0a5d | ||
|
|
95d55b8da1 | ||
|
|
f83c49baa3 | ||
|
|
cf0aad391c | ||
|
|
42732990cd | ||
|
|
f82246171b | ||
|
|
5b50eb18fc | ||
|
|
29824a8cf6 | ||
|
|
0db26fc3ab | ||
|
|
8991fe2e90 | ||
|
|
2211770d8b | ||
|
|
e25113bcf0 | ||
|
|
e1535d2bd8 | ||
|
|
d5bf68d77d | ||
|
|
5b95fd0521 | ||
|
|
fcacba268d | ||
|
|
d7eaeaf636 | ||
|
|
2e13c3cdfd | ||
|
|
d726afd9e4 | ||
|
|
1480a6ca14 | ||
|
|
02a07f19a1 | ||
|
|
d2ed39f103 | ||
|
|
8b15f18993 | ||
|
|
b256e3a44f | ||
|
|
939274281a | ||
|
|
be4b100ae5 | ||
|
|
f99d4ba7c4 | ||
|
|
1f4e9681f7 | ||
|
|
f56256f488 | ||
|
|
f18e2933d4 | ||
|
|
2f819d1647 | ||
|
|
821df406c9 | ||
|
|
3bb7c75db3 | ||
|
|
c94eaa0e6c | ||
|
|
a16439e38e | ||
|
|
b6e613c771 | ||
|
|
c5f230e682 | ||
|
|
ba0375bf06 | ||
|
|
13ad532412 | ||
|
|
8ecc311bcc | ||
|
|
e3831d8ecc | ||
|
|
9c0536deda | ||
|
|
6b42bd7abf | ||
|
|
0d246aa435 | ||
|
|
c5f35b7ff9 | ||
|
|
ff602cb906 | ||
|
|
1806e5511e | ||
|
|
cb93316fed | ||
|
|
a6f0fa90f7 | ||
|
|
30a16e3a87 | ||
|
|
3db46fa9bf | ||
|
|
12cb82af91 | ||
|
|
d49b514aa6 | ||
|
|
b6e1d82685 | ||
|
|
6cd5c8fca5 | ||
|
|
67aee78fdf | ||
|
|
c48db4fbba | ||
|
|
f8b03f5750 | ||
|
|
2c07829be2 | ||
|
|
652c694244 | ||
|
|
995fa3af36 | ||
|
|
4323b35198 | ||
|
|
fd50f5465f | ||
|
|
13d2c470be | ||
|
|
b690a8be2f | ||
|
|
e85804efa2 | ||
|
|
e26ad2026c | ||
|
|
03162970cd | ||
|
|
bc2b7d4f09 | ||
|
|
f77d6b7a2d | ||
|
|
1fdb16866b | ||
|
|
6ebf14143a | ||
|
|
cf5dac9563 | ||
|
|
2e1c825b90 | ||
|
|
a974ce6257 | ||
|
|
5d81cb6ac7 | ||
|
|
41356ac267 | ||
|
|
86af599a18 | ||
|
|
95e36dfe74 | ||
|
|
24b5f62090 | ||
|
|
989e636d98 | ||
|
|
eec78fbd1e | ||
|
|
70d4cf2cd9 | ||
|
|
52692e299d | ||
|
|
fd2bc150d8 | ||
|
|
267afa5a3b | ||
|
|
7ec153889c | ||
|
|
efc795920b | ||
|
|
d3fd287efb | ||
|
|
0fa19ed555 | ||
|
|
52fdf5b7ec | ||
|
|
a09196c4ae | ||
|
|
1d8997633c | ||
|
|
0898b6b482 | ||
|
|
848b8b983e | ||
|
|
465d08d99f | ||
|
|
f07510e2b6 | ||
|
|
b8b391ad18 | ||
|
|
81dae2f88e | ||
|
|
74811679b7 | ||
|
|
93f5fcae1e | ||
|
|
92d4e3e75a | ||
|
|
03f1aea069 | ||
|
|
6da88339f5 | ||
|
|
e0e8d5061d | ||
|
|
62e73b17d2 | ||
|
|
799a90ecfa | ||
|
|
ef168979bf | ||
|
|
2093cf425f | ||
|
|
a3462daeb1 | ||
|
|
a334a941c4 | ||
|
|
1cdb8abf30 | ||
|
|
fbdb5beb59 | ||
|
|
2f372ab4d6 | ||
|
|
524ce43e23 | ||
|
|
7f8e139413 | ||
|
|
99d79d0a80 | ||
|
|
0ca1bf3cfd | ||
|
|
c18984c452 | ||
|
|
445c0b1482 | ||
|
|
0590c2a4f6 | ||
|
|
81ec856a0f | ||
|
|
2410bc603b | ||
|
|
45cadbd4f3 | ||
|
|
02a5a678f6 | ||
|
|
98f534e172 | ||
|
|
a68c8cf5f1 | ||
|
|
604fc92943 | ||
|
|
008d93928f | ||
|
|
601619660d | ||
|
|
4aa07c3547 | ||
|
|
f3f7c5cc57 | ||
|
|
c035046999 | ||
|
|
e15cd64ac9 | ||
|
|
59a4ac71f9 | ||
|
|
7c04351a57 | ||
|
|
46f787950a | ||
|
|
6a244b3a8d | ||
|
|
3cf8b9ea86 | ||
|
|
df8a14e12a | ||
|
|
f6ec26075d | ||
|
|
c42206db02 | ||
|
|
bb64012914 | ||
|
|
d5cc53a4e1 | ||
|
|
55100918cc | ||
|
|
faee571850 | ||
|
|
6f422785c3 | ||
|
|
a7affc93ba | ||
|
|
9052131aef | ||
|
|
6b5e0efd1e | ||
|
|
62eb7ebeba | ||
|
|
c48fd9d842 | ||
|
|
e150dd4a66 | ||
|
|
b3d73e0aff | ||
|
|
16946a6f00 | ||
|
|
a4383075af | ||
|
|
20a60be550 | ||
|
|
7afefcf75d | ||
|
|
40b3443c8f | ||
|
|
e3167068d9 | ||
|
|
cc964b4609 | ||
|
|
370a84192e | ||
|
|
4104ff2b6a | ||
|
|
a0162dacf6 | ||
|
|
b2cc186d22 | ||
|
|
235a6617c4 | ||
|
|
218a8c4d90 | ||
|
|
e68d6e7924 | ||
|
|
dc72aa2305 | ||
|
|
93b10bcf3c | ||
|
|
4971e3735e | ||
|
|
6d56abcec1 | ||
|
|
5d63abb473 | ||
|
|
6e67bb7ae6 | ||
|
|
d67835260d | ||
|
|
b085344b91 | ||
|
|
c108eaba42 | ||
|
|
6ce3ce69b9 | ||
|
|
6826521ec5 | ||
|
|
5fe62660aa | ||
|
|
7a28f68ad0 | ||
|
|
ea9d44bede | ||
|
|
fd3692b36f | ||
|
|
cd7b6fdbc1 | ||
|
|
571e17410a | ||
|
|
797fbbf826 | ||
|
|
a37b5c9c61 | ||
|
|
30f3baabaf | ||
|
|
ef29f321e0 | ||
|
|
15bca92b2c | ||
|
|
71f6bc41eb | ||
|
|
6d2f16a7ae | ||
|
|
40b279e3a3 | ||
|
|
5d8b089188 | ||
|
|
9686d93ff6 | ||
|
|
67ebe16b40 | ||
|
|
6ab6488e5a | ||
|
|
ffdbefe22c | ||
|
|
456e2d7ed5 | ||
|
|
fa3d1f98e0 | ||
|
|
c21b69e73e | ||
|
|
9318bd3b0d | ||
|
|
59448d635c | ||
|
|
a9a4fb641f | ||
|
|
f247b3b99b | ||
|
|
fa62c5afb6 | ||
|
|
061c7b633f | ||
|
|
dacc07136c | ||
|
|
abfc37076a | ||
|
|
9a0f388f66 | ||
|
|
b08e6221e0 | ||
|
|
0efda9cd6b | ||
|
|
f4ebbcbf70 | ||
|
|
36ecad6cbe | ||
|
|
22568a3d26 | ||
|
|
8e798e4c28 | ||
|
|
736e340bde | ||
|
|
05c93ff3ae | ||
|
|
8d4c65f259 | ||
|
|
0435d9c338 | ||
|
|
15a5f3278a | ||
|
|
34bbd0ded1 | ||
|
|
c17f37857c | ||
|
|
a2e09b4c9d | ||
|
|
5013155e58 | ||
|
|
7575e119d6 | ||
|
|
3b9b897af3 | ||
|
|
0cfd21cc15 | ||
|
|
05a98b6be0 | ||
|
|
52b9363745 | ||
|
|
f947fafec9 | ||
|
|
68d3cdd722 | ||
|
|
5770dc58b9 | ||
|
|
36da7a918f | ||
|
|
782d2fab83 | ||
|
|
d9c5d3c868 | ||
|
|
9b3122e92c | ||
|
|
f44d4a1d86 | ||
|
|
33a2943e8c | ||
|
|
a1a7e7cd24 | ||
|
|
6957911657 | ||
|
|
7cc36b7703 | ||
|
|
9407b42f97 | ||
|
|
151f29a17a | ||
|
|
f7dc354f42 | ||
|
|
4d870f665b | ||
|
|
0635423e73 | ||
|
|
3f34bf4465 | ||
|
|
9f0fdc68a9 | ||
|
|
701b4130bd | ||
|
|
d27bccdff1 | ||
|
|
5ff03ce5ac | ||
|
|
6eea2a409e | ||
|
|
ea74820176 | ||
|
|
50de1a6885 | ||
|
|
055d100548 | ||
|
|
63efd26767 | ||
|
|
8d2cb0ef9b | ||
|
|
2bff6e5188 | ||
|
|
453d0494fb | ||
|
|
97c6073d39 | ||
|
|
9fe6fa7f44 | ||
|
|
7699ed3fc8 | ||
|
|
5eca556fe7 | ||
|
|
4602c00dcf | ||
|
|
629d66e0b9 | ||
|
|
859c132ee2 | ||
|
|
99a0e2469b | ||
|
|
2548c43175 | ||
|
|
90bcaaf582 | ||
|
|
da8307cd26 | ||
|
|
cfa06c3f38 | ||
|
|
906965b48b | ||
|
|
d5bbbbd41d | ||
|
|
8e05229e62 | ||
|
|
7a8d50a803 | ||
|
|
6630cfbe16 | ||
|
|
dd25fbcb4b | ||
|
|
f9ac73732b | ||
|
|
26342588ab | ||
|
|
29191eb2c7 | ||
|
|
168d546304 | ||
|
|
34133ca7f3 | ||
|
|
4b32f16747 | ||
|
|
99c900946d | ||
|
|
39213a1847 | ||
|
|
c18b1328a5 | ||
|
|
93ef6aefce | ||
|
|
2e9e1909da | ||
|
|
4f67e8d0c3 | ||
|
|
30cba446f2 | ||
|
|
dda65c0877 | ||
|
|
cf80199bfc | ||
|
|
6694330bb2 | ||
|
|
a5a49c350d | ||
|
|
6ae2d74fca | ||
|
|
29ad012763 | ||
|
|
9570cedff6 | ||
|
|
d3871ed774 | ||
|
|
34db8df6d9 | ||
|
|
092706eff8 | ||
|
|
f4a1a5e94c | ||
|
|
dadfaed829 | ||
|
|
e365943a70 | ||
|
|
86fcfc74da | ||
|
|
eecebbf186 | ||
|
|
8dc1737e39 | ||
|
|
34bb9b5766 | ||
|
|
299e01722f | ||
|
|
97ee4578c9 | ||
|
|
0d3f9ba913 | ||
|
|
6aa44d62ad | ||
|
|
5641ee3f94 | ||
|
|
2e9fbbc978 | ||
|
|
ad634c0a94 | ||
|
|
7190f46938 | ||
|
|
e27cd96494 | ||
|
|
4caa45b8bb | ||
|
|
f3473b9eba | ||
|
|
06a984e4ff | ||
|
|
53f10f4d46 | ||
|
|
ed0cd78e05 | ||
|
|
faf04b009b | ||
|
|
965bad626a | ||
|
|
69445cb4a0 | ||
|
|
30c97391d7 | ||
|
|
cacb8d410e | ||
|
|
4b388ee902 | ||
|
|
10865f9952 | ||
|
|
dfaccdd03b | ||
|
|
f812260c23 | ||
|
|
b6da6569c4 | ||
|
|
bbcef2fd33 | ||
|
|
ec3cbf81c4 | ||
|
|
1a471b0a45 | ||
|
|
73b8aa8bcc | ||
|
|
394045f68a | ||
|
|
f9af8e0390 | ||
|
|
1260349384 | ||
|
|
74f4ed5fd2 | ||
|
|
91725ddced | ||
|
|
e055e4a092 | ||
|
|
f26cc3b957 | ||
|
|
9a3b1ec222 | ||
|
|
9141d11a7d | ||
|
|
6dc4f31ba1 | ||
|
|
d294aa4356 | ||
|
|
f314ee3d6a | ||
|
|
581ad6fc29 | ||
|
|
8ff7d934b2 | ||
|
|
5bdebf5ab0 | ||
|
|
96250b7ad3 | ||
|
|
7c9278bd92 | ||
|
|
4205c91609 | ||
|
|
75c4075345 | ||
|
|
f8398339a3 | ||
|
|
9bf9e7ac5c | ||
|
|
567b21b1d6 | ||
|
|
fa7d63d9d1 | ||
|
|
46a94cce56 | ||
|
|
bc50202d0d | ||
|
|
8fc8e158e2 | ||
|
|
06e7d087f2 | ||
|
|
fbff38de33 | ||
|
|
19b4002f25 | ||
|
|
b47cc4bc66 | ||
|
|
e307ceeee7 | ||
|
|
4745c7a00d | ||
|
|
5c783e1a63 | ||
|
|
05ad0c9e06 | ||
|
|
6d7b5c9513 | ||
|
|
de001e05da | ||
|
|
08ce0579aa | ||
|
|
be60600a47 | ||
|
|
f2265b10e4 | ||
|
|
afa865587e | ||
|
|
9ea353569a | ||
|
|
1bc59f7290 | ||
|
|
563a20fc82 | ||
|
|
6cca1fc512 | ||
|
|
6833f96c14 | ||
|
|
2304c145f3 | ||
|
|
fa6f697dbb | ||
|
|
91a98f919d | ||
|
|
616dbd67f7 | ||
|
|
6fc0fd315c | ||
|
|
9de2549dfb | ||
|
|
81fb420457 | ||
|
|
8b77f1db2c | ||
|
|
a154e2ea1a | ||
|
|
5fe8d574ca | ||
|
|
a9dc7fa7cc | ||
|
|
9d3d7426aa | ||
|
|
a597c66afe | ||
|
|
21fefbc8f6 | ||
|
|
38020d9068 | ||
|
|
1b0a5eb54a | ||
|
|
071f7aea82 | ||
|
|
32b3f7f2d2 | ||
|
|
576217d33a | ||
|
|
b8b595c6b2 | ||
|
|
a93445f3fe | ||
|
|
dbcb3dd1ae | ||
|
|
d6ab6ee370 | ||
|
|
c9294e30d9 | ||
|
|
d7715f71ad | ||
|
|
b2ed0a902b | ||
|
|
18159c85b9 | ||
|
|
d7755de116 | ||
|
|
7631921366 | ||
|
|
803abb58f9 | ||
|
|
a3250dfac7 | ||
|
|
4f9158e533 | ||
|
|
e624b9aa6a | ||
|
|
2fc1b9b5e0 | ||
|
|
026375da49 | ||
|
|
58a629b02e | ||
|
|
df6590abfc | ||
|
|
33af9948e5 | ||
|
|
8ab6298f30 | ||
|
|
78c308c835 | ||
|
|
8a2bf21cee | ||
|
|
59f44c1189 | ||
|
|
02219dcd79 | ||
|
|
f0d207f380 | ||
|
|
7dd09cecda | ||
|
|
e75b68e391 | ||
|
|
8d360c5a57 | ||
|
|
f6900f0689 | ||
|
|
8759a5a63e | ||
|
|
52bdbc42bb | ||
|
|
28e00b68fd | ||
|
|
2ff09158f3 | ||
|
|
6764c26954 | ||
|
|
040159c02f | ||
|
|
61c6c83de4 | ||
|
|
0be32c9d42 | ||
|
|
aa1bf31bcb | ||
|
|
c023b0532a | ||
|
|
f8aaba6704 | ||
|
|
26cf42049d | ||
|
|
06d4f39e7b | ||
|
|
a1e36a9a37 | ||
|
|
11da41e106 | ||
|
|
7a5b9152e9 | ||
|
|
7876d533cf | ||
|
|
e99de88c5c | ||
|
|
bcb82da88f | ||
|
|
592fd61788 | ||
|
|
3c875267af | ||
|
|
455ce37398 | ||
|
|
64befb27eb | ||
|
|
177565567e | ||
|
|
8045e56df2 | ||
|
|
206a4e17b5 | ||
|
|
2785bf9cb2 | ||
|
|
bc2f2ad546 | ||
|
|
4fce730326 | ||
|
|
9206f363ff | ||
|
|
130e33a4e7 | ||
|
|
a36989a860 | ||
|
|
1946343d5b | ||
|
|
4ccf43d753 | ||
|
|
7ca68c6492 | ||
|
|
61a869a1f5 | ||
|
|
c718951e97 | ||
|
|
04ea044917 | ||
|
|
66219f23bb | ||
|
|
187a12e90a | ||
|
|
356c0bf751 | ||
|
|
7a9c873093 | ||
|
|
d7537777c3 | ||
|
|
145aefc9d1 | ||
|
|
2b2e20da24 | ||
|
|
a977c79f9f | ||
|
|
f52ec0df7c | ||
|
|
54043df8fb | ||
|
|
fad1e108d8 | ||
|
|
fc3e82584b | ||
|
|
a0afb6ec8e | ||
|
|
549deb51d6 | ||
|
|
4f842d9f1b | ||
|
|
9627fe6be6 | ||
|
|
b8ddb11796 | ||
|
|
f04cc227a6 | ||
|
|
811bc1b8e5 | ||
|
|
ccb291ce66 | ||
|
|
676f5c4b31 | ||
|
|
14083a0857 | ||
|
|
b4f5b5556f | ||
|
|
fa4f9197ee | ||
|
|
bfb5a678d2 | ||
|
|
d2572315ca | ||
|
|
467b774d13 | ||
|
|
78a1424582 | ||
|
|
82d6aa0c97 | ||
|
|
1213578eb7 | ||
|
|
268d027770 | ||
|
|
f55fbe037a | ||
|
|
3a95ff7435 | ||
|
|
d70715a635 | ||
|
|
54a9058ee0 | ||
|
|
efb5256d28 | ||
|
|
a4c0fead1f | ||
|
|
35775b3bc5 | ||
|
|
7417d8e86e | ||
|
|
df84c466c1 | ||
|
|
bf3a8c6383 | ||
|
|
5605e46acb | ||
|
|
3346c7f455 | ||
|
|
b78b2b6b35 | ||
|
|
0f43d5df6a | ||
|
|
30b9d7f00e | ||
|
|
b9f49cee45 | ||
|
|
c144580c98 | ||
|
|
2ff8c12bf9 | ||
|
|
335cffe9a9 | ||
|
|
bc40ab378c | ||
|
|
d81276607c | ||
|
|
3bc3b34d97 | ||
|
|
f0a1d69f50 | ||
|
|
0672936134 | ||
|
|
3632478b8d | ||
|
|
c07fa70d58 | ||
|
|
ee7f2413ed | ||
|
|
12ebf21be5 | ||
|
|
691eea9b45 | ||
|
|
7e6f3364bc | ||
|
|
3f430627df | ||
|
|
3160c03843 | ||
|
|
420a3f4a01 | ||
|
|
9eb48312c7 | ||
|
|
469caa1a14 | ||
|
|
3aca8a938c | ||
|
|
01d46a1751 | ||
|
|
9c859d2655 | ||
|
|
fb5dbe13c2 | ||
|
|
e4c359d8b9 | ||
|
|
52256d7a73 | ||
|
|
aa974c0dc3 | ||
|
|
23d3539fcb | ||
|
|
bcff7274f4 | ||
|
|
e9deaf2ca5 | ||
|
|
e1bceb2adb | ||
|
|
34428fc709 | ||
|
|
393274d142 | ||
|
|
a8e08d14bb | ||
|
|
bf9b9026d9 | ||
|
|
0f096f9ad4 | ||
|
|
db55e596d2 | ||
|
|
82c5aa82d2 | ||
|
|
742d1889c5 | ||
|
|
61042c7606 | ||
|
|
3e4f7228a0 | ||
|
|
76e0e09aca | ||
|
|
e4deffcbe8 | ||
|
|
de5f902487 | ||
|
|
cab9237d95 | ||
|
|
6ecf9e091c | ||
|
|
aa69598b57 | ||
|
|
f47084968d | ||
|
|
6a8e8e92a7 | ||
|
|
c7edde6ca4 | ||
|
|
379e2c694b | ||
|
|
29d5f5d760 | ||
|
|
258bc85b9c | ||
|
|
fc1d4f5362 | ||
|
|
cda222d2ec | ||
|
|
07b4228988 | ||
|
|
ad1eee7aa5 | ||
|
|
9c1b3735b4 | ||
|
|
ab0338f6ae | ||
|
|
39fc16954b | ||
|
|
f5289c546e | ||
|
|
721f924e15 | ||
|
|
6611c16099 | ||
|
|
2c5151726c | ||
|
|
5eff7f38df | ||
|
|
e9ca4305a6 | ||
|
|
125deafc84 | ||
|
|
1445673e18 | ||
|
|
4a17d8ef97 | ||
|
|
b4fff6b9b7 | ||
|
|
2245b0ac94 | ||
|
|
e561beab44 | ||
|
|
3bcd9d747b | ||
|
|
85a71a3923 | ||
|
|
a30751464a | ||
|
|
1678548353 | ||
|
|
7218c45443 | ||
|
|
bd914d49f1 | ||
|
|
fed112e497 | ||
|
|
c3be4c4629 | ||
|
|
286d678785 | ||
|
|
42ae135d38 | ||
|
|
42f5d4404d | ||
|
|
5c098dc7ad | ||
|
|
3dba6fc95c | ||
|
|
1eee82272a | ||
|
|
da5b7bea78 | ||
|
|
910cdc0537 | ||
|
|
02a501705a | ||
|
|
a9d9fb5d75 | ||
|
|
ffbc7e723d | ||
|
|
3ef56576d3 | ||
|
|
cde8e02bf2 | ||
|
|
1d24e96074 | ||
|
|
be432c8654 | ||
|
|
3778a69fbe | ||
|
|
d807a5c314 | ||
|
|
5862a05fb1 | ||
|
|
dba14bfe90 | ||
|
|
2e257f40e6 | ||
|
|
cdb2bec909 | ||
|
|
dd5061d73b | ||
|
|
7a18a0fb34 | ||
|
|
28d3f74614 | ||
|
|
98c7b23178 | ||
|
|
89dc8c2004 | ||
|
|
e274fc732b |
258
.github/CODEOWNERS
vendored
Normal file
258
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1,258 @@
|
||||
* @rycee
|
||||
|
||||
/flake.nix @bqv @kisik21
|
||||
|
||||
/modules/home-environment.nix @rycee
|
||||
|
||||
/modules/misc/dconf.nix @gnidorah @rycee
|
||||
|
||||
/modules/misc/fontconfig.nix @rycee
|
||||
/tests/modules/misc/fontconfig @rycee
|
||||
|
||||
/modules/misc/gtk.nix @rycee
|
||||
|
||||
/modules/config/i18n.nix @midchildan
|
||||
/tests/modules/config/i18n @midchildan
|
||||
|
||||
/modules/misc/news.nix @rycee
|
||||
|
||||
/modules/misc/numlock.nix @evanjs
|
||||
/tests/modules/misc/numlock @evanjs
|
||||
|
||||
/modules/misc/pam.nix @rycee
|
||||
/tests/modules/misc/pam @rycee
|
||||
|
||||
/modules/misc/qt.nix @rycee
|
||||
|
||||
/modules/misc/submodule-support.nix @rycee
|
||||
|
||||
/modules/misc/tmpfiles.nix @dawidsowa
|
||||
|
||||
/modules/misc/vte.nix @rycee
|
||||
|
||||
/modules/misc/xdg-mime-apps.nix @pacien
|
||||
|
||||
/modules/misc/xdg-user-dirs.nix @pacien
|
||||
|
||||
/modules/programs/aria2.nix @JustinLovinger
|
||||
|
||||
/modules/programs/autojump.nix @evanjs
|
||||
/tests/modules/programs/autojump @evanjs
|
||||
|
||||
/modules/programs/autorandr.nix @uvNikita
|
||||
|
||||
/modules/programs/bash.nix @rycee
|
||||
|
||||
/modules/programs/bat.nix @marsam
|
||||
|
||||
/modules/programs/beets.nix @rycee
|
||||
|
||||
/modules/programs/broot.nix @aheaume
|
||||
|
||||
/modules/programs/dircolors.nix @JustinLovinger
|
||||
|
||||
/modules/programs/direnv.nix @rycee
|
||||
|
||||
/modules/programs/eclipse.nix @rycee
|
||||
|
||||
/modules/programs/emacs.nix @rycee
|
||||
|
||||
/modules/programs/firefox.nix @rycee
|
||||
|
||||
/modules/programs/gh.nix @Gerschtli
|
||||
/tests/modules/programs/gh @Gerschtli
|
||||
|
||||
/modules/programs/git.nix @rycee
|
||||
|
||||
/modules/programs/gnome-terminal.nix @rycee
|
||||
|
||||
/modules/programs/go.nix @rvolosatovs
|
||||
|
||||
/modules/programs/home-manager.nix @rycee
|
||||
|
||||
/modules/programs/i3status.nix @JustinLovinger
|
||||
|
||||
/modules/programs/i3status-rust.nix @workflow
|
||||
|
||||
/modules/programs/keychain.nix @marsam
|
||||
|
||||
/modules/programs/lesspipe.nix @rycee
|
||||
|
||||
/modules/programs/lf.nix @owm111
|
||||
/tests/modules/programs/lf @owm111
|
||||
|
||||
/modules/programs/lieer.nix @tadfisher
|
||||
|
||||
/modules/programs/lsd.nix @marsam
|
||||
|
||||
/modules/programs/matplotlib.nix @rprospero
|
||||
|
||||
/modules/programs/mbsync.nix @KarlJoad
|
||||
/tests/modules/programs/mbsync @KarlJoad
|
||||
|
||||
/modules/programs/mcfly.nix @marsam
|
||||
|
||||
/modules/programs/mpv.nix @tadeokondrak @thiagokokada
|
||||
/tests/modules/programs/mpv @thiagokokada
|
||||
|
||||
/modules/programs/mu.nix @KarlJoad
|
||||
|
||||
/modules/programs/ncmpcpp.nix @olmokramer
|
||||
/tests/modules/programs/ncmpcpp @olmokramer
|
||||
/tests/modules/programs/ncmpcpp-linux @olmokramer
|
||||
|
||||
/modules/programs/ne.nix @cwyc
|
||||
/tests/modules/programs/ne @cwyc
|
||||
|
||||
/modules/programs/noti.nix @marsam
|
||||
|
||||
/modules/programs/nushell.nix @Philipp-M
|
||||
/tests/modules/programs/nushell @Philipp-M
|
||||
|
||||
/modules/programs/obs-studio.nix @adisbladis
|
||||
|
||||
/modules/programs/octant.nix @06kellyjac
|
||||
|
||||
/modules/programs/opam.nix @marsam
|
||||
|
||||
/modules/programs/openssh.nix @rycee
|
||||
|
||||
/modules/programs/password-store.nix @pacien
|
||||
|
||||
/modules/programs/pazi.nix @marsam
|
||||
|
||||
/modules/programs/pidgin.nix @rycee
|
||||
|
||||
/modules/programs/powerline-go.nix @DamienCassou
|
||||
|
||||
/modules/programs/rofi.nix @thiagokokada
|
||||
/tests/modules/programs/rofi @thiagokokada
|
||||
|
||||
/modules/programs/rofi-pass.nix @seylerius
|
||||
/tests/modules/programs/rofi-pass @seylerius
|
||||
|
||||
/modules/programs/rtorrent.nix @marsam
|
||||
|
||||
/modules/programs/sbt.nix @kubukoz
|
||||
/tests/modules/programs/sbt @kubukoz
|
||||
|
||||
/modules/programs/ssh.nix @rycee
|
||||
|
||||
/modules/programs/starship.nix @marsam
|
||||
|
||||
/modules/programs/texlive.nix @rycee
|
||||
|
||||
/modules/programs/waybar.nix @berbiche
|
||||
/tests/modules/programs/waybar @berbiche
|
||||
|
||||
/modules/programs/z-lua.nix @marsam
|
||||
|
||||
/modules/programs/zathura.nix @rprospero
|
||||
|
||||
/modules/programs/zoxide.nix @marsam
|
||||
|
||||
/modules/programs/zsh/prezto.nix @NickHu
|
||||
|
||||
/modules/services/caffeine.nix @uvNikita
|
||||
|
||||
/modules/services/cbatticon.nix @pmiddend
|
||||
|
||||
/modules/services/clipmenu.nix @DamienCassou
|
||||
|
||||
/modules/services/dropbox.nix @eyJhb
|
||||
/tests/modules/services/dropbox @eyJhb
|
||||
|
||||
/modules/services/dunst.nix @rycee
|
||||
|
||||
/modules/services/emacs.nix @tadfisher
|
||||
|
||||
/modules/services/flameshot.nix @moredhel
|
||||
|
||||
/modules/services/fluidsynth.nix @Valodim
|
||||
|
||||
/modules/services/gnome-keyring.nix @rycee
|
||||
|
||||
/modules/services/gpg-agent.nix @rycee
|
||||
|
||||
/modules/services/grobi.nix @mbrgm
|
||||
|
||||
/modules/services/hound.nix @adisbladis
|
||||
|
||||
/modules/services/imapnotify.nix @nickhu
|
||||
|
||||
/modules/services/kanshi.nix @nurelin
|
||||
/tests/modules/services/kanshi @nurelin
|
||||
|
||||
/modules/services/kdeconnect.nix @adisbladis
|
||||
|
||||
/modules/services/keepassx.nix @rycee
|
||||
|
||||
/modules/services/lieer.nix @tadfisher
|
||||
|
||||
/modules/services/lorri.nix @Gerschtli
|
||||
|
||||
/modules/services/mako.nix @onny
|
||||
|
||||
/modules/services/mbsync.nix @pjones
|
||||
|
||||
/modules/services/mpdris2.nix @pjones
|
||||
|
||||
/modules/services/muchsync.nix @pacien
|
||||
|
||||
/modules/services/network-manager-applet.nix @rycee
|
||||
|
||||
/modules/services/parcellite.nix @gleber
|
||||
|
||||
/modules/services/password-store-sync.nix @pacien
|
||||
|
||||
/modules/services/pasystray.nix @pltanton
|
||||
|
||||
/modules/services/pbgopy.nix @ivarwithoutbones
|
||||
/tests/modules/services/pbgopy @ivarwithoutbones
|
||||
|
||||
/modules/services/plan9port.nix @ehmry
|
||||
|
||||
/modules/services/playerctld.nix @fendse
|
||||
/tests/modules/playerctld @fendse
|
||||
|
||||
/modules/services/pulseeffects.nix @jonringer
|
||||
|
||||
/modules/services/random-background.nix @rycee
|
||||
|
||||
/modules/services/redshift-gammastep @rycee @petabyteboy @thiagokokada
|
||||
/tests/modules/redshift-gammastep @thiagokokada
|
||||
|
||||
/modules/services/status-notifier-watcher.nix @pltanton
|
||||
|
||||
/modules/services/syncthing.nix @rycee
|
||||
|
||||
/modules/services/taffybar.nix @rycee
|
||||
|
||||
/modules/services/tahoe-lafs.nix @rycee
|
||||
|
||||
/modules/services/taskwarrior-sync.nix @minijackson @pacien
|
||||
|
||||
/modules/services/udiskie.nix @rycee
|
||||
|
||||
/modules/services/unison.nix @pacien
|
||||
|
||||
/modules/services/window-managers/i3-sway/sway.nix @alexarice
|
||||
|
||||
/modules/services/wlsunset.nix @matrss
|
||||
/tests/modules/services/wlsunset @matrss
|
||||
|
||||
/modules/services/xcape.nix @nickhu
|
||||
|
||||
/modules/services/xembed-sni-proxy.nix @rycee
|
||||
|
||||
/modules/services/xscreensaver.nix @rycee
|
||||
|
||||
/modules/services/xsuspender.nix @offlinehacker
|
||||
|
||||
/modules/systemd.nix @rycee
|
||||
|
||||
/modules/xcursor.nix @league
|
||||
|
||||
/modules/xresources.nix @rycee
|
||||
|
||||
/modules/xsession.nix @rycee
|
||||
38
.github/ISSUE_TEMPLATE.md
vendored
Normal file
38
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<!--
|
||||
|
||||
If you are encountering the error
|
||||
|
||||
element xref: validity error : IDREF attribute linkend references an unknown ID "opt-home.file._name__.source"
|
||||
|
||||
then it means that you are using an old version of Home Manager, such
|
||||
as the release-20.03 branch, with a recent version of Nixpkgs, such as
|
||||
version 20.09 or master. See https://git.io/JTb6K for more.
|
||||
|
||||
In general, please check if there already exists a relevant issue
|
||||
before creating a new one.
|
||||
|
||||
-->
|
||||
|
||||
### Issue description
|
||||
|
||||
<!--
|
||||
Please describe the issue. For support and help please use the IRC
|
||||
channel #home-manager @ freenode.net instead.
|
||||
-->
|
||||
|
||||
### Meta
|
||||
|
||||
#### Maintainer CC
|
||||
|
||||
<!--
|
||||
Please @ people who are in the `meta.maintainers` list of the
|
||||
offending module. If in doubt, check `git blame` for whoever last
|
||||
touched something.
|
||||
-->
|
||||
|
||||
#### Technical details
|
||||
|
||||
<!--
|
||||
Please run `nix-shell -p nix-info --run "nix-info -m"` and paste the
|
||||
result.
|
||||
-->
|
||||
44
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
44
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
### Description
|
||||
|
||||
<!--
|
||||
|
||||
Please provide a brief description of your change.
|
||||
|
||||
-->
|
||||
|
||||
### Checklist
|
||||
|
||||
<!--
|
||||
|
||||
Please go through the following checklist before opening a non-WIP
|
||||
pull-request.
|
||||
|
||||
Also make sure to read the guidelines found at
|
||||
|
||||
https://github.com/nix-community/home-manager/blob/master/doc/contributing.adoc#sec-guidelines
|
||||
|
||||
-->
|
||||
|
||||
- [ ] Change is backwards compatible.
|
||||
|
||||
- [ ] Code formatted with `./format`.
|
||||
|
||||
- [ ] Code tested through `nix-shell --pure tests -A run.all`.
|
||||
|
||||
- [ ] Test cases updated/added. See [example](https://github.com/nix-community/home-manager/commit/f3fbb50b68df20da47f9b0def5607857fcc0d021#diff-b61a6d542f9036550ba9c401c80f00ef).
|
||||
|
||||
- [ ] Commit messages are formatted like
|
||||
|
||||
```
|
||||
{component}: {description}
|
||||
|
||||
{long description}
|
||||
```
|
||||
|
||||
See [CONTRIBUTING](https://github.com/nix-community/home-manager/blob/master/doc/contributing.adoc#sec-commit-style) for more information and [recent commit messages](https://github.com/nix-community/home-manager/commits/master) for examples.
|
||||
|
||||
- If this PR adds a new module
|
||||
|
||||
- [ ] Added myself as module maintainer. See [example](https://github.com/nix-community/home-manager/blob/068ff76a10e95820f886ac46957edcff4e44621d/modules/programs/lesspipe.nix#L6).
|
||||
|
||||
- [ ] Added myself and the module files to `.github/CODEOWNERS`.
|
||||
17
.github/dependabot.yml
vendored
Normal file
17
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
target-branch: "master"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
commit-message:
|
||||
prefix: "ci:"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
target-branch: "release-20.09"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
commit-message:
|
||||
prefix: "ci:"
|
||||
28
.github/workflows/github_pages.yml
vendored
Normal file
28
.github/workflows/github_pages.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: GitHub Pages
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
publish:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: cachix/install-nix-action@v13
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@v10
|
||||
with:
|
||||
name: nix-community
|
||||
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
|
||||
- run: |
|
||||
nix-build -A docs.html
|
||||
cp -r result/share/doc/home-manager public
|
||||
- name: Deploy
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./public
|
||||
23
.github/workflows/test.yml
vendored
Normal file
23
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: Test
|
||||
on:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: "30 2 * * *"
|
||||
jobs:
|
||||
tests:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: cachix/install-nix-action@v13
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@v10
|
||||
with:
|
||||
name: nix-community
|
||||
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
|
||||
- run: ./format -c
|
||||
- run: nix-shell . -A install
|
||||
- run: nix-shell --pure tests -A run.all
|
||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/flake.lock
|
||||
/result*
|
||||
43
.gitlab-ci.yml
Normal file
43
.gitlab-ci.yml
Normal file
@@ -0,0 +1,43 @@
|
||||
image: nixos/nix:latest
|
||||
|
||||
variables:
|
||||
NIX_PATH: "nixpkgs=channel:nixos-unstable"
|
||||
|
||||
stages:
|
||||
- test
|
||||
- deploy
|
||||
|
||||
Run tests:
|
||||
stage: test
|
||||
script:
|
||||
- nix-shell --pure tests -A run.files-text
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == "master"
|
||||
when: always
|
||||
|
||||
pages:
|
||||
stage: deploy
|
||||
script:
|
||||
- mkdir -p ~/.config/nixpkgs
|
||||
- echo '{ manual.html.enable = true; }' > ~/.config/nixpkgs/home.nix
|
||||
- nix-shell . -A install
|
||||
- mkdir public
|
||||
- cp -r ~/.nix-profile/share/doc/home-manager/* public/
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == "master"
|
||||
when: always
|
||||
|
||||
Deploy NUR:
|
||||
stage: deploy
|
||||
variables:
|
||||
HM_BRANCH: $CI_COMMIT_REF_NAME
|
||||
HM_COMMIT_SHA: $CI_COMMIT_SHA
|
||||
trigger:
|
||||
project: rycee/nur-expressions
|
||||
branch: master
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == "master" || $CI_COMMIT_BRANCH =~ /^release-/
|
||||
when: always
|
||||
1
CONTRIBUTING.adoc
Symbolic link
1
CONTRIBUTING.adoc
Symbolic link
@@ -0,0 +1 @@
|
||||
doc/contributing.adoc
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Robert Helgesson
|
||||
Copyright (c) 2017-2020 Home Manager contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
273
README.md
273
README.md
@@ -3,15 +3,28 @@ Home Manager using Nix
|
||||
|
||||
This project provides a basic system for managing a user environment
|
||||
using the [Nix][] package manager together with the Nix libraries
|
||||
found in [Nixpkgs][]. Before attempting to use Home Manager please
|
||||
read the warning below.
|
||||
found in [Nixpkgs][]. It allows declarative configuration of user
|
||||
specific (non global) packages and dotfiles.
|
||||
|
||||
Before attempting to use Home Manager please read the warning below.
|
||||
|
||||
For a more systematic overview of Home Manager and its available
|
||||
options, please see the [Home Manager manual][manual].
|
||||
|
||||
Words of warning
|
||||
----------------
|
||||
|
||||
This project is under development. I personally use it to manage
|
||||
several user configurations but it may fail catastrophically for you.
|
||||
So beware!
|
||||
Unfortunately, it is quite possible to get difficult to understand
|
||||
errors when working with Home Manager, such as infinite loops with no
|
||||
clear source reference. You should therefore be comfortable using the
|
||||
Nix language and the various tools in the Nix ecosystem. Reading
|
||||
through the [Nix Pills][] document is a good way to familiarize
|
||||
yourself with them.
|
||||
|
||||
If you are not very familiar with Nix but still want to use Home
|
||||
Manager then you are strongly encouraged to start with a small and
|
||||
very simple configuration and gradually make it more elaborate as you
|
||||
learn.
|
||||
|
||||
In some cases Home Manager cannot detect whether it will overwrite a
|
||||
previous manual configuration. For example, the Gnome Terminal module
|
||||
@@ -19,73 +32,121 @@ will write to your dconf store and cannot tell whether a configuration
|
||||
that it is about to be overwrite was from a previous Home Manager
|
||||
generation or from manual configuration.
|
||||
|
||||
Home Manager targets [NixOS][] version 17.03 (the current stable
|
||||
version), it may or may not work on other Linux distributions and
|
||||
NixOS versions.
|
||||
Home Manager targets [NixOS][] unstable and NixOS version 20.09 (the
|
||||
current stable version), it may or may not work on other Linux
|
||||
distributions and NixOS versions.
|
||||
|
||||
Also, the `home-manager` tool does not explicitly support rollbacks at
|
||||
the moment so if your home directory gets messed up you'll have to fix
|
||||
it yourself (you can attempt to run the activation script for the
|
||||
desired generation).
|
||||
it yourself. See the [rollbacks](#rollbacks) section for instructions
|
||||
on how to manually perform a rollback.
|
||||
|
||||
Now when your expectations have been built up and you are eager to try
|
||||
all this out you can go ahead and read the rest of this text.
|
||||
|
||||
Contact
|
||||
-------
|
||||
|
||||
You can chat with us on IRC in the channel [#home-manager][] on
|
||||
[freenode][]. The [channel logs][] are hosted courtesy of
|
||||
[samueldr][].
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Currently the easiest way to install Home Manager is as follows:
|
||||
|
||||
1. Make sure you have a working Nix installation. If you are not
|
||||
using NixOS then you may here have to run
|
||||
1. Make sure you have a working Nix installation. Specifically, make
|
||||
sure that your user is able to build and install Nix packages. For
|
||||
example, you should be able to successfully run a command like
|
||||
`nix-instantiate '<nixpkgs>' -A hello` without having to switch to
|
||||
the root user. For a multi-user install of Nix this means that
|
||||
your user must be covered by the
|
||||
[`allowed-users`][nixAllowedUsers] Nix option. On NixOS you can
|
||||
control this option using the
|
||||
[`nix.allowedUsers`][nixosAllowedUsers] system option.
|
||||
|
||||
```
|
||||
$ mkdir -m 0755 -p /nix/var/nix/{profiles,gcroots}/per-user/$USER
|
||||
Note that Nix 2.4 (`nixUnstable`) is not yet supported.
|
||||
|
||||
2. Add the appropriate Home Manager channel. If you are following
|
||||
Nixpkgs master or an unstable channel you can run
|
||||
|
||||
```console
|
||||
$ nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager
|
||||
$ nix-channel --update
|
||||
```
|
||||
|
||||
since Home Manager uses these directories to manage your profile
|
||||
generations. On NixOS these should already be available.
|
||||
and if you follow a Nixpkgs version 20.09 channel you can run
|
||||
|
||||
2. Clone the Home Manager repository into the `~/.config/nixpkgs`
|
||||
directory:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/rycee/home-manager ~/.config/nixpkgs/home-manager
|
||||
```console
|
||||
$ nix-channel --add https://github.com/nix-community/home-manager/archive/release-20.09.tar.gz home-manager
|
||||
$ nix-channel --update
|
||||
```
|
||||
|
||||
3. Add Home Manager to your user's Nixpkgs, for example by adding it
|
||||
to the `packageOverrides` section in your
|
||||
`~/.config/nixpkgs/config.nix` file:
|
||||
On NixOS you may need to log out and back in for the channel to
|
||||
become available. On non-NixOS you may have to add
|
||||
|
||||
```nix
|
||||
{
|
||||
packageOverrides = pkgs: rec {
|
||||
home-manager = import ./home-manager { inherit pkgs; };
|
||||
};
|
||||
}
|
||||
```shell
|
||||
export NIX_PATH=$HOME/.nix-defexpr/channels${NIX_PATH:+:}$NIX_PATH
|
||||
```
|
||||
|
||||
4. Install the `home-manager` package:
|
||||
to your shell (see [nix#2033](https://github.com/NixOS/nix/issues/2033)).
|
||||
|
||||
3. Install Home Manager and create the first Home Manager generation:
|
||||
|
||||
```console
|
||||
$ nix-shell '<home-manager>' -A install
|
||||
```
|
||||
|
||||
Once finished, Home Manager should be active and available in your
|
||||
user environment.
|
||||
|
||||
3. If you do not plan on having Home Manager manage your shell
|
||||
configuration then you must source the
|
||||
|
||||
```
|
||||
$ nix-env -f '<nixpkgs>' -iA home-manager
|
||||
installing ‘home-manager’
|
||||
$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh
|
||||
```
|
||||
|
||||
file in your shell configuration. Unfortunately, in this specific
|
||||
case we currently only support POSIX.2-like shells such as
|
||||
[Bash][] or [Z shell][].
|
||||
|
||||
For example, if you use Bash then add
|
||||
|
||||
```bash
|
||||
. "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh"
|
||||
```
|
||||
|
||||
or this when managing home configuration together with system
|
||||
configuration
|
||||
|
||||
```bash
|
||||
. "/etc/profiles/per-user/$USER/etc/profile.d/hm-session-vars.sh"
|
||||
```
|
||||
|
||||
to your `~/.profile` file.
|
||||
|
||||
If instead of using channels you want to run Home Manager from a Git
|
||||
checkout of the repository then you can use the
|
||||
`programs.home-manager.path` option to specify the absolute path to
|
||||
the repository.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The `home-manager` package installs a tool that is conveniently called
|
||||
`home-manager`. This tool can apply configurations to your home
|
||||
Home Manager is typically managed through the `home-manager` tool.
|
||||
This tool can, for example, apply configurations to your home
|
||||
directory, list user packages installed by the tool, and list the
|
||||
configuration generations.
|
||||
|
||||
As an example, let us set up a very simple configuration that installs
|
||||
the htop and fortune packages, installs Emacs with a few extra
|
||||
packages enabled, installs Firefox with Adobe Flash enabled, and
|
||||
enables the user gpg-agent service.
|
||||
As an example, let us expand the initial configuration file from the
|
||||
installation above to install the htop and fortune packages, install
|
||||
Emacs with a few extra packages enabled, install Firefox with
|
||||
smooth scrolling enabled, and enable the user gpg-agent service.
|
||||
|
||||
First create a file `~/.config/nixpkgs/home.nix` containing
|
||||
To satisfy the above setup we should elaborate the
|
||||
`~/.config/nixpkgs/home.nix` file as follows:
|
||||
|
||||
```nix
|
||||
{ pkgs, ... }:
|
||||
@@ -106,7 +167,13 @@ First create a file `~/.config/nixpkgs/home.nix` containing
|
||||
|
||||
programs.firefox = {
|
||||
enable = true;
|
||||
enableAdobeFlash = true;
|
||||
profiles = {
|
||||
myprofile = {
|
||||
settings = {
|
||||
"general.smoothScroll" = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.gpg-agent = {
|
||||
@@ -114,28 +181,75 @@ First create a file `~/.config/nixpkgs/home.nix` containing
|
||||
defaultCacheTtl = 1800;
|
||||
enableSshSupport = true;
|
||||
};
|
||||
|
||||
programs.home-manager = {
|
||||
enable = true;
|
||||
path = "…";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
To activate this configuration you can then run
|
||||
|
||||
```
|
||||
```console
|
||||
$ home-manager switch
|
||||
```
|
||||
|
||||
or if you are not feeling so lucky,
|
||||
|
||||
```
|
||||
```console
|
||||
$ home-manager build
|
||||
```
|
||||
|
||||
which will create a `result` link to a directory containing an
|
||||
activation script and the generated home directory files.
|
||||
|
||||
Documentation of available configuration options, including
|
||||
descriptions and usage examples, is available in the [Home Manager
|
||||
manual][configuration options] or offline by running
|
||||
|
||||
```console
|
||||
$ man home-configuration.nix
|
||||
```
|
||||
|
||||
Rollbacks
|
||||
---------
|
||||
|
||||
While the `home-manager` tool does not explicitly support rollbacks at
|
||||
the moment it is relatively easy to perform one manually. The steps to
|
||||
do so are
|
||||
|
||||
1. Run `home-manager generations` to determine which generation you
|
||||
wish to rollback to:
|
||||
|
||||
```console
|
||||
$ home-manager generations
|
||||
2018-01-04 11:56 : id 765 -> /nix/store/kahm1rxk77mnvd2l8pfvd4jkkffk5ijk-home-manager-generation
|
||||
2018-01-03 10:29 : id 764 -> /nix/store/2wsmsliqr5yynqkdyjzb1y57pr5q2lsj-home-manager-generation
|
||||
2018-01-01 12:21 : id 763 -> /nix/store/mv960kl9chn2lal5q8lnqdp1ygxngcd1-home-manager-generation
|
||||
2017-12-29 21:03 : id 762 -> /nix/store/6c0k1r03fxckql4vgqcn9ccb616ynb94-home-manager-generation
|
||||
2017-12-25 18:51 : id 761 -> /nix/store/czc5y6vi1rvnkfv83cs3rn84jarcgsgh-home-manager-generation
|
||||
…
|
||||
```
|
||||
|
||||
2. Copy the Nix store path of the generation you chose, e.g.,
|
||||
|
||||
/nix/store/mv960kl9chn2lal5q8lnqdp1ygxngcd1-home-manager-generation
|
||||
|
||||
for generation 763.
|
||||
|
||||
3. Run the `activate` script inside the copied store path:
|
||||
|
||||
```console
|
||||
$ /nix/store/mv960kl9chn2lal5q8lnqdp1ygxngcd1-home-manager-generation/activate
|
||||
Starting home manager activation
|
||||
…
|
||||
```
|
||||
|
||||
Keeping your ~ safe from harm
|
||||
-----------------------------
|
||||
|
||||
To configure programs and services the Home Manager must write various
|
||||
To configure programs and services Home Manager must write various
|
||||
things to your home directory. To prevent overwriting any existing
|
||||
files when switching to a new generation, Home Manager will attempt to
|
||||
detect collisions between existing files and generated files. If any
|
||||
@@ -143,7 +257,7 @@ such collision is detected the activation will terminate before
|
||||
changing anything on your computer.
|
||||
|
||||
For example, suppose you have a wonderful, painstakingly created
|
||||
`~/.gitconfig` and add
|
||||
`~/.config/git/config` and add
|
||||
|
||||
```nix
|
||||
{
|
||||
@@ -162,7 +276,7 @@ For example, suppose you have a wonderful, painstakingly created
|
||||
to your configuration. Attempting to switch to the generation will
|
||||
then result in
|
||||
|
||||
```
|
||||
```console
|
||||
$ home-manager switch
|
||||
…
|
||||
Activating checkLinkTargets
|
||||
@@ -196,7 +310,7 @@ in your system configuration and
|
||||
# …
|
||||
|
||||
xsession.enable = true;
|
||||
xsession.windowManager = "…";
|
||||
xsession.windowManager.command = "…";
|
||||
|
||||
# …
|
||||
}
|
||||
@@ -204,6 +318,71 @@ in your system configuration and
|
||||
|
||||
in your Home Manager configuration.
|
||||
|
||||
Nix Flakes
|
||||
----------
|
||||
|
||||
Home Manager includes a `flake.nix` file for compatibility with [Nix Flakes][]
|
||||
for those that wish to use it as a module. A bare-minimum `flake.nix` would be
|
||||
as follows:
|
||||
|
||||
```nix
|
||||
{
|
||||
description = "NixOS configuration";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||
home-manager.url = "github:nix-community/home-manager";
|
||||
};
|
||||
|
||||
outputs = { home-manager, nixpkgs, ... }: {
|
||||
nixosConfigurations = {
|
||||
hostname = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./configuration.nix
|
||||
home-manager.nixosModules.home-manager
|
||||
{
|
||||
home-manager.useGlobalPkgs = true;
|
||||
home-manager.useUserPackages = true;
|
||||
home-manager.users.jdoe = import ./home.nix;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Note, the Home Manager library is exported by the flake under
|
||||
`lib.hm`.
|
||||
|
||||
When using flakes, switch to new configurations as you do for the
|
||||
whole system (e. g. `nixos-rebuild switch --flake <path>`) instead of
|
||||
using the `home-manager` command line tool.
|
||||
|
||||
Releases
|
||||
--------
|
||||
|
||||
Home Manager is developed against `nixpkgs-unstable` branch, which
|
||||
often causes it to contain tweaks for changes/packages not yet
|
||||
released in stable NixOS. To avoid breaking users' configurations,
|
||||
Home Manager is released in branches corresponding to NixOS releases
|
||||
(e.g. `release-20.09`). These branches get fixes, but usually not new
|
||||
modules. If you need a module to be backported, then feel free to open
|
||||
an issue.
|
||||
|
||||
[Bash]: https://www.gnu.org/software/bash/
|
||||
[Nix]: https://nixos.org/nix/
|
||||
[NixOS]: https://nixos.org/
|
||||
[Nixpkgs]: https://nixos.org/nixpkgs/
|
||||
[nixAllowedUsers]: https://nixos.org/nix/manual/#conf-allowed-users
|
||||
[nixosAllowedUsers]: https://nixos.org/nixos/manual/options.html#opt-nix.allowedUsers
|
||||
[Z shell]: http://zsh.sourceforge.net/
|
||||
[manual]: https://nix-community.github.io/home-manager/
|
||||
[configuration options]: https://nix-community.github.io/home-manager/options.html
|
||||
[#home-manager]: https://webchat.freenode.net/?url=irc%3A%2F%2Firc.freenode.net%2Fhome-manager
|
||||
[freenode]: https://freenode.net/
|
||||
[channel logs]: https://logs.nix.samueldr.com/home-manager/
|
||||
[samueldr]: https://github.com/samueldr/
|
||||
[Nix Pills]: https://nixos.org/nixos/nix-pills/
|
||||
[Nix Flakes]: https://nixos.wiki/wiki/Flakes
|
||||
|
||||
20
default.nix
20
default.nix
@@ -1,2 +1,18 @@
|
||||
# Simply defer to the home-manager script derivation.
|
||||
import ./home-manager
|
||||
{ pkgs ? import <nixpkgs> { } }:
|
||||
|
||||
rec {
|
||||
docs = with import ./doc { inherit pkgs; }; {
|
||||
html = manual.html;
|
||||
manPages = manPages;
|
||||
json = options.json;
|
||||
};
|
||||
|
||||
home-manager = pkgs.callPackage ./home-manager { path = toString ./.; };
|
||||
|
||||
install =
|
||||
pkgs.callPackage ./home-manager/install.nix { inherit home-manager; };
|
||||
|
||||
nixos = import ./nixos;
|
||||
|
||||
path = ./.;
|
||||
}
|
||||
|
||||
258
doc/contributing.adoc
Normal file
258
doc/contributing.adoc
Normal file
@@ -0,0 +1,258 @@
|
||||
[[ch-contributing]]
|
||||
== Contributing
|
||||
|
||||
:open-issues: https://github.com/nix-community/home-manager/issues
|
||||
:new-issue: https://github.com/nix-community/home-manager/issues/new
|
||||
:fork-a-repo: https://help.github.com/articles/fork-a-repo/
|
||||
:create-a-pull-request: https://help.github.com/articles/creating-a-pull-request/
|
||||
:seven-rules: https://chris.beams.io/posts/git-commit/#seven-rules
|
||||
:news-nix: https://github.com/nix-community/home-manager/blob/master/modules/misc/news.nix
|
||||
:nixfmt: https://github.com/serokell/nixfmt/
|
||||
:example-commit-message: https://github.com/nix-community/home-manager/commit/69f8e47e9e74c8d3d060ca22e18246b7f7d988ef
|
||||
|
||||
Contributions to Home Manager are very welcome. To make the process as smooth as possible for both you and the Home Manager maintainers we provide some guidelines that we ask you to follow. See <<sec-contrib-getting-started>> for information on how to set up a suitable development environment and <<sec-guidelines>> for the actual guidelines.
|
||||
|
||||
This text is mainly directed at those who would like to make code contributions to Home Manager. If you just want to report a bug then first look among the already {open-issues}[open issues], if you find one matching yours then feel free to comment on it to add any additional information you may have. If no matching issue exists then go to the {new-issue}[new issue] page and write a description of your problem. Include as much information as you can, ideally also include relevant excerpts from your Home Manager configuration.
|
||||
|
||||
[[sec-contrib-getting-started]]
|
||||
=== Getting started
|
||||
|
||||
If you have not previously forked Home Manager then you need to do that first. Have a look at GitHub's {fork-a-repo}[Fork a repo] for instructions on how to do this.
|
||||
|
||||
Once you have a fork of Home Manager you should create a branch starting at the most recent `master` branch. Give your branch a reasonably descriptive name. Commit your changes to this branch and when you are happy with the result and it fulfills <<sec-guidelines>> then push the branch to GitHub and {create-a-pull-request}[create a pull request].
|
||||
|
||||
Assuming your clone is at `$HOME/devel/home-manager` then you can make the `home-manager` command use it by either
|
||||
|
||||
1. overriding the default path by using the `-I` command line option:
|
||||
+
|
||||
[source,console]
|
||||
$ home-manager -I home-manager=$HOME/devel/home-manager
|
||||
+
|
||||
or
|
||||
|
||||
2. changing the default path by ensuring your configuration includes
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
programs.home-manager.enable = true;
|
||||
programs.home-manager.path = "$HOME/devel/home-manager";
|
||||
----
|
||||
+
|
||||
and running `home-manager switch` to activate the change. Afterwards, `home-manager build` and `home-manager switch` will use your cloned repository.
|
||||
|
||||
The first option is good if you only temporarily want to use your clone.
|
||||
|
||||
[[sec-guidelines]]
|
||||
=== Guidelines
|
||||
:irc-home-manager: https://webchat.freenode.net/?url=irc%3A%2F%2Firc.freenode.net%2Fhome-manager
|
||||
:valuable-options: https://github.com/Infinisil/rfcs/blob/config-option/rfcs/0042-config-option.md#valuable-options
|
||||
:rfc-42: https://github.com/Infinisil/rfcs/blob/config-option/rfcs/0042-config-option.md
|
||||
:assertions: https://nixos.org/manual/nixos/stable/index.html#sec-assertions
|
||||
|
||||
If your contribution satisfy the following rules then there is a good chance it will be merged without too much trouble. The rules are enforced by the Home Manager maintainers and to a lesser extent the Home Manager CI system.
|
||||
|
||||
If you are uncertain how these rules affect the change you would like to make then feel free to start a discussion in the {irc-home-manager}[#home-manager] IRC channel, ideally before you start developing.
|
||||
|
||||
[[sec-guidelines-back-compat]]
|
||||
==== Maintain backward compatibility
|
||||
|
||||
Your contribution should not cause another user's existing configuration to break unless there is a very good reason and the change should be announced to the user through an {assertions}[assertion] or similar.
|
||||
|
||||
Remember that Home Manager is used in many different environments and you should consider how your change may effect others. For example,
|
||||
|
||||
- Does your change work for people that do not use NixOS? Consider other GNU/Linux distributions and macOS.
|
||||
- Does your change work for people whose configuration is built on one system and deployed on another system?
|
||||
|
||||
[[sec-guidelines-forward-compat]]
|
||||
==== Keep forward compatibility in mind
|
||||
|
||||
The master branch of Home Manager tracks the unstable channel of Nixpkgs, which may update package versions at any time. It is therefore important to consider how a package update may affect your code and try to reduce the risk of breakage.
|
||||
|
||||
The most effective way to reduce this risk is to follow the advice in <<sec-guidelines-valuable-options>>.
|
||||
|
||||
[[sec-guidelines-valuable-options]]
|
||||
==== Add only valuable options
|
||||
|
||||
When creating a new module it is tempting to include every option supported by the software. This is _strongly_ discouraged. Providing many options increases maintenance burden and risk of breakage considerably. This is why only the most {valuable-options}[important software options] should be modeled explicitly. Less important options should be expressible through an `extraConfig` escape hatch.
|
||||
|
||||
A good rule of thumb for the first implementation of a module is to only add explicit options for those settings that absolutely must be set for the software to function correctly. It follows that a module for software that provides sensible default values for all settings would require no explicit options at all.
|
||||
|
||||
If the software uses a structured configuration format like a JSON, YAML, INI, TOML, or even a plain list of key/value pairs then consider using a `settings` option as described in {rfc-42}[Nix RFC 42].
|
||||
|
||||
[[sec-guidelines-add-tests]]
|
||||
==== Add relevant tests
|
||||
|
||||
If at all possible, make sure to add new tests and expand existing tests so that your change will keep working in the future. See <<sec-tests>> for more information about the Home Manager test suite.
|
||||
|
||||
All contributed code _must_ pass the test suite.
|
||||
|
||||
[[sec-guidelines-module-maintainer]]
|
||||
|
||||
==== Add relevant documentation
|
||||
:docbook: https://tdg.docbook.org/
|
||||
:asciidoc: https://asciidoc.org/
|
||||
:docbook-rocks: https://berbiche.github.io/docbook.rocks/
|
||||
|
||||
Many code changes require changing the documentation as well. Module options should be documented with DocBook. See {docbook-rocks}[DocBook rocks!] for a quick introduction and {docbook}[DocBook 5: The Definitive Guide] for in-depth information of DocBook. Home Manager is itself documented using a combination of DocBook and {asciidoc}[AsciiDoc]. All text is hosted in Home Manager's Git repository.
|
||||
|
||||
The HTML version of the manual containing both the module option descriptions and the documentation of Home Manager can be generated and opened by typing the following in a shell within a clone of the Home Manager Git repository:
|
||||
|
||||
[source,console]
|
||||
$ nix-build -A docs.html
|
||||
$ xdg-open ./result/share/doc/home-manager/index.html
|
||||
|
||||
When you have made changes to a module, it is a good idea to check that the man page version of the module options looks good:
|
||||
|
||||
[source,console]
|
||||
$ nix-build -A docs.manPages
|
||||
$ man ./result/share/man/man5/home-configuration.nix.5
|
||||
|
||||
==== Add yourself as a module maintainer
|
||||
|
||||
Every new module _must_ include a named maintainer using the `meta.maintainers` attribute. If you are a user of a module that currently lacks a maintainer then please consider adopting it.
|
||||
|
||||
If you are present in the NixOS maintainer list then you can use that entry. If you are not then you can add yourself to `modules/lib/maintainers.nix` in the Home Manager project.
|
||||
|
||||
Also add yourself to `.github/CODEOWNERS` as owner of the associated module files, including the test files. You will then be automatically added as a reviewer on any new pull request that touches your files.
|
||||
|
||||
Maintainers are encouraged to join the IRC channel and participate when they have opportunity.
|
||||
|
||||
[[sec-guidelines-code-style]]
|
||||
==== Format your code
|
||||
|
||||
Make sure your code is formatted as described in <<sec-code-style>>. To maintain consistency throughout the project you are encouraged to browse through existing code and adopt its style also in new code.
|
||||
|
||||
[[sec-guidelines-commit-message-style]]
|
||||
==== Format your commit messages
|
||||
|
||||
Similar to <<sec-guidelines-code-style>> we encourage a consistent commit message format as described in <<sec-commit-style>>.
|
||||
|
||||
[[sec-guidelines-news-style]]
|
||||
==== Format your news entries
|
||||
|
||||
If your contribution includes a change that should be communicated to users of Home Manager then you can add a news entry. The entry must be formatted as described in <<sec-news>>.
|
||||
|
||||
When new modules are added a news entry should be included but you do not need to create this entry manually. The merging maintainer will create the entry for you. This is to reduce the risk of merge conflicts.
|
||||
|
||||
[[sec-guidelines-conditional-modules]]
|
||||
==== Use conditional modules and news
|
||||
|
||||
Home Manager includes a number of modules that are only usable on some of the supported platforms. The most common example of platform specific modules are those that define systemd user services, which only works on Linux systems.
|
||||
|
||||
If you add a module that is platform specific then make sure to include a condition in the `loadModule` function call. This will make the module accessible only on systems where the condition evaluates to `true`.
|
||||
|
||||
Similarly, if you are adding a news entry then it should be shown only to users that may find it relevant, see <<sec-news>> for a description of conditional news.
|
||||
|
||||
[[sec-guidelines-licensing]]
|
||||
==== Mind the license
|
||||
|
||||
The Home Manager project is covered by the MIT license and we can only accept contributions that fall under this license, or are licensed in a compatible way. When you contribute self written code and documentation it is assumed that you are doing so under the MIT license.
|
||||
|
||||
A potential gotcha with respect to licensing are option descriptions. Often it is convenient to copy from the upstream software documentation. When this is done it is important to verify that the license of the upstream documentation allows redistribution under the terms of the MIT license.
|
||||
|
||||
[[sec-commit-style]]
|
||||
=== Commits
|
||||
|
||||
The commits in your pull request should be reasonably self-contained, that is, each commit should make sense in isolation. In particular, you will be asked to amend any commit that introduces syntax errors or similar problems even if they are fixed in a later commit.
|
||||
|
||||
The commit messages should follow the {seven-rules}[seven rules]. We also ask you to include the affected code component or module in the first line. That is, a commit message should follow the template
|
||||
|
||||
----
|
||||
{component}: {description}
|
||||
|
||||
{long description}
|
||||
----
|
||||
|
||||
where `{component}` refers to the code component (or module) your change affects, `{description}` is a very brief description of your change, and `{long description}` is an optional clarifying description. Note, `{description}` should start with a lower case letter. As a rare exception, if there is no clear component, or your change affects many components, then the `{component}` part is optional. See <<ex-commit-message>> for a commit message that fulfills these requirements.
|
||||
|
||||
[[ex-commit-message]]
|
||||
.Compliant commit message
|
||||
===============================================================================
|
||||
The commit {example-commit-message}[69f8e47e9e74c8d3d060ca22e18246b7f7d988ef] contains the commit message
|
||||
|
||||
----
|
||||
starship: allow running in Emacs if vterm is used
|
||||
|
||||
The vterm buffer is backed by libvterm and can handle Starship prompts
|
||||
without issues.
|
||||
----
|
||||
|
||||
which ticks all the boxes necessary to be accepted in Home Manager.
|
||||
===============================================================================
|
||||
|
||||
Finally, when adding a new module, say `programs/foo.nix`, we use the fixed commit format `foo: add module`. You can, of course, still include a long description if you wish.
|
||||
|
||||
[[sec-code-style]]
|
||||
=== Code Style
|
||||
|
||||
The code in Home Manager is formatted by the {nixfmt}[nixfmt] tool and the formatting is checked in the pull request tests. Run the `format` tool inside the project repository before submitting your pull request.
|
||||
|
||||
Keep lines at a reasonable width, ideally 80 characters or less. This also applies to string literals.
|
||||
|
||||
We prefer `lowerCamelCase` for variable and attribute names with the accepted exception of variables directly referencing packages in Nixpkgs which use a hyphenated style. For example, the Home Manager option `services.gpg-agent.enableSshSupport` references the `gpg-agent` package in Nixpkgs.
|
||||
|
||||
[[sec-news]]
|
||||
=== News
|
||||
|
||||
Home Manager includes a system for presenting news to the user. When making a change you, therefore, have the option to also include an associated news entry. In general, a news entry should only be added for truly noteworthy news. For example, a bug fix or new option does generally not need a news entry.
|
||||
|
||||
If you do have a change worthy of a news entry then please add one in {news-nix}[`news.nix`] but you should follow some basic guidelines:
|
||||
|
||||
- The entry timestamp should be in ISO-8601 format having "+00:00" as time zone. For example, "2017-09-13T17:10:14+00:00". A suitable timestamp can be produced by the command
|
||||
+
|
||||
[source,console]
|
||||
$ date --iso-8601=second --universal
|
||||
|
||||
- The entry condition should be as specific as possible. For example, if you are changing or deprecating a specific option then you could restrict the news to those users who actually use this option.
|
||||
|
||||
- Wrap the news message so that it will fit in the typical terminal, that is, at most 80 characters wide. Ideally a bit less.
|
||||
|
||||
- Unlike commit messages, news will be read without any connection to the Home Manager source code. It is therefore important to make the message understandable in isolation and to those who do not have knowledge of the Home Manager internals. To this end it should be written in more descriptive, prose like way.
|
||||
|
||||
- If you refer to an option then write its full attribute path. That is, instead of writing
|
||||
+
|
||||
----
|
||||
The option 'foo' has been deprecated, please use 'bar' instead.
|
||||
----
|
||||
+
|
||||
it should read
|
||||
+
|
||||
----
|
||||
The option 'services.myservice.foo' has been deprecated, please
|
||||
use 'services.myservice.bar' instead.
|
||||
----
|
||||
|
||||
- A new module, say `foo.nix`, should always include a news entry that has a message along the lines of
|
||||
+
|
||||
----
|
||||
A new module is available: 'services.foo'.
|
||||
----
|
||||
+
|
||||
If the module is platform specific, e.g., a service module using systemd, then a condition like
|
||||
+
|
||||
[source,nix]
|
||||
condition = hostPlatform.isLinux;
|
||||
+
|
||||
should be added. If you contribute a module then you don't need to add this entry, the merger will create an entry for you.
|
||||
|
||||
[[sec-tests]]
|
||||
=== Tests
|
||||
|
||||
Home Manager includes a basic test suite and it is highly recommended to include at least one test when adding a module. Tests are typically in the form of "golden tests" where, for example, a generated configuration file is compared to a known correct file.
|
||||
|
||||
It is relatively easy to create tests by modeling the existing tests, found in the `tests` project directory.
|
||||
|
||||
The full Home Manager test suite can be run by executing
|
||||
|
||||
[source,console]
|
||||
$ nix-shell --pure tests -A run.all
|
||||
|
||||
in the project root. List all test cases through
|
||||
|
||||
[source,console]
|
||||
$ nix-shell --pure tests -A list
|
||||
|
||||
and run an individual test, for example `alacritty-empty-settings`, through
|
||||
|
||||
[source,console]
|
||||
$ nix-shell --pure tests -A run.alacritty-empty-settings
|
||||
120
doc/default.nix
Normal file
120
doc/default.nix
Normal file
@@ -0,0 +1,120 @@
|
||||
{ pkgs
|
||||
|
||||
# Note, this should be "the standard library" + HM extensions.
|
||||
, lib ? import ../modules/lib/stdlib-extended.nix pkgs.lib }:
|
||||
|
||||
let
|
||||
|
||||
nmdSrc = pkgs.fetchFromGitLab {
|
||||
name = "nmd";
|
||||
owner = "rycee";
|
||||
repo = "nmd";
|
||||
rev = "2398aa79ab12aa7aba14bc3b08a6efd38ebabdc5";
|
||||
sha256 = "0yxb48afvccn8vvpkykzcr4q1rgv8jsijqncia7a5ffzshcrwrnh";
|
||||
};
|
||||
|
||||
nmd = import nmdSrc { inherit lib pkgs; };
|
||||
|
||||
# Make sure the used package is scrubbed to avoid actually
|
||||
# instantiating derivations.
|
||||
scrubbedPkgsModule = {
|
||||
imports = [{
|
||||
_module.args = {
|
||||
pkgs = lib.mkForce (nmd.scrubDerivations "pkgs" pkgs);
|
||||
pkgs_i686 = lib.mkForce { };
|
||||
};
|
||||
}];
|
||||
};
|
||||
|
||||
buildModulesDocs = args:
|
||||
nmd.buildModulesDocs ({
|
||||
moduleRootPaths = [ ./.. ];
|
||||
mkModuleUrl = path:
|
||||
"https://github.com/nix-community/home-manager/blob/master/${path}#blob-path";
|
||||
channelName = "home-manager";
|
||||
} // args);
|
||||
|
||||
hmModulesDocs = buildModulesDocs {
|
||||
modules = import ../modules/modules.nix {
|
||||
inherit lib pkgs;
|
||||
check = false;
|
||||
} ++ [ scrubbedPkgsModule ];
|
||||
docBook.id = "home-manager-options";
|
||||
};
|
||||
|
||||
nixosModuleDocs = buildModulesDocs {
|
||||
modules = let
|
||||
nixosModule = module: pkgs.path + "/nixos/modules" + module;
|
||||
mockedNixos = with lib; {
|
||||
options = {
|
||||
environment.pathsToLink = mkSinkUndeclaredOptions { };
|
||||
systemd.services = mkSinkUndeclaredOptions { };
|
||||
users.users = mkSinkUndeclaredOptions { };
|
||||
};
|
||||
};
|
||||
in [
|
||||
../nixos/default.nix
|
||||
mockedNixos
|
||||
(nixosModule "/misc/assertions.nix")
|
||||
scrubbedPkgsModule
|
||||
];
|
||||
docBook = {
|
||||
id = "nixos-options";
|
||||
optionIdPrefix = "nixos-opt";
|
||||
};
|
||||
};
|
||||
|
||||
nixDarwinModuleDocs = buildModulesDocs {
|
||||
modules = let
|
||||
nixosModule = module: pkgs.path + "/nixos/modules" + module;
|
||||
mockedNixDarwin = with lib; {
|
||||
options = {
|
||||
environment.pathsToLink = mkSinkUndeclaredOptions { };
|
||||
system.activationScripts.postActivation.text =
|
||||
mkSinkUndeclaredOptions { };
|
||||
users.users = mkSinkUndeclaredOptions { };
|
||||
};
|
||||
};
|
||||
in [
|
||||
../nix-darwin/default.nix
|
||||
mockedNixDarwin
|
||||
(nixosModule "/misc/assertions.nix")
|
||||
scrubbedPkgsModule
|
||||
];
|
||||
docBook = {
|
||||
id = "nix-darwin-options";
|
||||
optionIdPrefix = "nix-darwin-opt";
|
||||
};
|
||||
};
|
||||
|
||||
docs = nmd.buildDocBookDocs {
|
||||
pathName = "home-manager";
|
||||
modulesDocs = [ hmModulesDocs nixDarwinModuleDocs nixosModuleDocs ];
|
||||
documentsDirectory = ./.;
|
||||
documentType = "book";
|
||||
chunkToc = ''
|
||||
<toc>
|
||||
<d:tocentry xmlns:d="http://docbook.org/ns/docbook" linkend="book-home-manager-manual"><?dbhtml filename="index.html"?>
|
||||
<d:tocentry linkend="ch-options"><?dbhtml filename="options.html"?></d:tocentry>
|
||||
<d:tocentry linkend="ch-nixos-options"><?dbhtml filename="nixos-options.html"?></d:tocentry>
|
||||
<d:tocentry linkend="ch-nix-darwin-options"><?dbhtml filename="nix-darwin-options.html"?></d:tocentry>
|
||||
<d:tocentry linkend="ch-tools"><?dbhtml filename="tools.html"?></d:tocentry>
|
||||
<d:tocentry linkend="ch-release-notes"><?dbhtml filename="release-notes.html"?></d:tocentry>
|
||||
</d:tocentry>
|
||||
</toc>
|
||||
'';
|
||||
};
|
||||
|
||||
in {
|
||||
inherit nmdSrc;
|
||||
|
||||
options = {
|
||||
json = hmModulesDocs.json.override {
|
||||
path = "share/doc/home-manager/options.json";
|
||||
};
|
||||
};
|
||||
|
||||
manPages = docs.manPages;
|
||||
|
||||
manual = { inherit (docs) html htmlOpenTool; };
|
||||
}
|
||||
171
doc/faq.adoc
Normal file
171
doc/faq.adoc
Normal file
@@ -0,0 +1,171 @@
|
||||
[[ch-faq]]
|
||||
== Frequently Asked Questions (FAQ)
|
||||
|
||||
=== Why is there a collision error when switching generation?
|
||||
|
||||
Home Manager currently installs packages into the user environment, precisely as if the packages were installed through `nix-env --install`. This means that you will get a collision error if your Home Manager configuration attempts to install a package that you already have installed manually, that is, packages that shows up when you run `nix-env --query`.
|
||||
|
||||
For example, imagine you have the `hello` package installed in your environment
|
||||
|
||||
[source,console]
|
||||
----
|
||||
$ nix-env --query
|
||||
hello-2.10
|
||||
----
|
||||
|
||||
and your Home Manager configuration contains
|
||||
|
||||
[source,nix]
|
||||
----
|
||||
home.packages = [ pkgs.hello ];
|
||||
----
|
||||
|
||||
Then attempting to switch to this configuration will result in an error similar to
|
||||
|
||||
[source,console]
|
||||
----
|
||||
$ home-manager switch
|
||||
these derivations will be built:
|
||||
/nix/store/xg69wsnd1rp8xgs9qfsjal017nf0ldhm-home-manager-path.drv
|
||||
[…]
|
||||
Activating installPackages
|
||||
replacing old ‘home-manager-path’
|
||||
installing ‘home-manager-path’
|
||||
building path(s) ‘/nix/store/b5c0asjz9f06l52l9812w6k39ifr49jj-user-environment’
|
||||
Wide character in die at /nix/store/64jc9gd2rkbgdb4yjx3nrgc91bpjj5ky-buildenv.pl line 79.
|
||||
collision between ‘/nix/store/fmwa4axzghz11cnln5absh31nbhs9lq1-home-manager-path/bin/hello’ and ‘/nix/store/c2wyl8b9p4afivpcz8jplc9kis8rj36d-hello-2.10/bin/hello’; use ‘nix-env --set-flag priority NUMBER PKGNAME’ to change the priority of one of the conflicting packages
|
||||
builder for ‘/nix/store/b37x3s7pzxbasfqhaca5dqbf3pjjw0ip-user-environment.drv’ failed with exit code 2
|
||||
error: build of ‘/nix/store/b37x3s7pzxbasfqhaca5dqbf3pjjw0ip-user-environment.drv’ failed
|
||||
----
|
||||
|
||||
The solution is typically to uninstall the package from the environment using `nix-env --uninstall` and reattempt the Home Manager generation switch.
|
||||
|
||||
=== Why are the session variables not set?
|
||||
|
||||
Home Manager is only able to set session variables automatically if it manages your Bash or Z shell configuration. If you don't want to let Home Manager manage your shell then you will have to manually source the `~/.nix-profile/etc/profile.d/hm-session-vars.sh` file in an appropriate way. In Bash and Z shell this can be done by adding
|
||||
|
||||
[source,bash]
|
||||
----
|
||||
. "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh"
|
||||
----
|
||||
|
||||
to your `.profile` and `.zshrc` files, respectively. The `hm-session-vars.sh` file should work in most Bourne-like shells.
|
||||
|
||||
=== How to set up a configuration for multiple users/machines?
|
||||
:post-your-homenix: https://www.reddit.com/r/NixOS/comments/9bb9h9/post_your_homemanager_homenix_file/
|
||||
|
||||
A typical way to prepare a repository of configurations for multiple logins and machines is to prepare one "top-level" file for each unique combination.
|
||||
|
||||
For example, if you have two machines, called "kronos" and "rhea" on which you want to configure your user "jane" then you could create the files
|
||||
|
||||
- `kronos-jane.nix`,
|
||||
- `rhea-jane.nix`, and
|
||||
- `common.nix`
|
||||
|
||||
in your repository. On the kronos and rhea machines you can then make `~jane/.config/nixpkgs/home.nix` be a symbolic link to the corresponding file in your configuration repository.
|
||||
|
||||
The `kronos-jane.nix` and `rhea-jane.nix` files follow the format
|
||||
|
||||
[source,nix]
|
||||
----
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
imports = [ ./common.nix ];
|
||||
|
||||
# Various options that are specific for this machine/user.
|
||||
}
|
||||
----
|
||||
|
||||
while the `common.nix` file contains configuration shared across the two logins. Of course, instead of just a single `common.nix` file you can have multiple ones, even one per program or service.
|
||||
|
||||
You can get some inspiration from the {post-your-homenix}[Post your home-manager home.nix file!] Reddit thread.
|
||||
|
||||
=== Why do I get an error message about `ca.desrt.dconf`?
|
||||
|
||||
You are most likely trying to configure the GTK or Gnome Terminal but the DBus session is not aware of the dconf service. The full error you might get is
|
||||
|
||||
----
|
||||
error: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name ca.desrt.dconf was not provided by any .service files
|
||||
----
|
||||
|
||||
The solution on NixOS is to add
|
||||
|
||||
[source,nix]
|
||||
services.dbus.packages = with pkgs; [ gnome3.dconf ];
|
||||
|
||||
to your system configuration.
|
||||
|
||||
=== How do I install packages from Nixpkgs unstable?
|
||||
|
||||
If you are using a stable version of Nixpkgs but would like to install some particular packages from Nixpkgs unstable – or some other channel – then you can import the unstable Nixpkgs and refer to its packages within your configuration. Something like
|
||||
|
||||
[source,nix]
|
||||
----
|
||||
{ pkgs, config, ... }:
|
||||
|
||||
let
|
||||
|
||||
pkgsUnstable = import <nixpkgs-unstable> {};
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
home.packages = [
|
||||
pkgsUnstable.foo
|
||||
];
|
||||
|
||||
# …
|
||||
}
|
||||
----
|
||||
|
||||
should work provided you have a Nix channel called `nixpkgs-unstable`.
|
||||
|
||||
You can add the `nixpkgs-unstable` channel by running
|
||||
|
||||
[source,console]
|
||||
----
|
||||
# nix-channel --add https://nixos.org/channels/nixpkgs-unstable nixpkgs-unstable
|
||||
# nix-channel --update
|
||||
----
|
||||
|
||||
Note, the package will not be affected by any package overrides, overlays, etc.
|
||||
|
||||
=== How do I override the package used by a module?
|
||||
:nixpkgs-overlays: https://nixos.org/nixpkgs/manual/#chap-overlays
|
||||
|
||||
By default Home Manager will install the package provided by your chosen `nixpkgs` channel but occasionally you might end up needing to change this package. This can typically be done in two ways.
|
||||
|
||||
1. If the module provides a `package` option, such as `programs.beets.package`, then this is the recommended way to perform the override. For example,
|
||||
+
|
||||
[source,nix]
|
||||
programs.beets.package = pkgs.beets.override { enableCheck = true; };
|
||||
|
||||
2. If no `package` option is available then you can typically override the relevant package using an {nixpkgs-overlays}[overlay].
|
||||
+
|
||||
For example, if you want to use the `programs.skim` module but use the `skim` package from Nixpkgs unstable, then a configuration like
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
{ pkgs, config, ... }:
|
||||
|
||||
let
|
||||
|
||||
pkgsUnstable = import <nixpkgs-unstable> {};
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
programs.skim.enable = true;
|
||||
|
||||
nixpkgs.overlays = [
|
||||
(self: super: {
|
||||
skim = pkgsUnstable.skim;
|
||||
})
|
||||
];
|
||||
|
||||
# …
|
||||
}
|
||||
----
|
||||
+
|
||||
should work OK.
|
||||
263
doc/installation.adoc
Normal file
263
doc/installation.adoc
Normal file
@@ -0,0 +1,263 @@
|
||||
[[ch-installation]]
|
||||
== Installing Home Manager
|
||||
|
||||
:nix-darwin: https://github.com/LnL7/nix-darwin/
|
||||
|
||||
Home Manager can be used in three primary ways:
|
||||
|
||||
1. Using the standalone `home-manager` tool. For platforms other than
|
||||
NixOS and Darwin, this is the only available choice. It is also
|
||||
recommended for people on NixOS or Darwin that want to manage their
|
||||
home directory independent of the system as a whole. See
|
||||
<<sec-install-standalone>> for instructions on how to perform this
|
||||
installation.
|
||||
|
||||
2. As a module within a NixOS system configuration. This allows the
|
||||
user profiles to be built together with the system when running
|
||||
`nixos-rebuild`. See <<sec-install-nixos-module>> for a description of
|
||||
this setup.
|
||||
|
||||
3. As a module within a {nix-darwin}[nix-darwin] system configuration.
|
||||
This allows the user profiles to be built together with the system
|
||||
when running `darwin-rebuild`. See <<sec-install-nix-darwin-module>>
|
||||
for a description of this setup.
|
||||
|
||||
[[sec-install-standalone]]
|
||||
=== Standalone installation
|
||||
|
||||
:nix-allowed-users: https://nixos.org/nix/manual/#conf-allowed-users
|
||||
:nixos-allowed-users: https://nixos.org/nixos/manual/options.html#opt-nix.allowedUsers
|
||||
|
||||
1. Make sure you have a working Nix installation. Specifically, make
|
||||
sure that your user is able to build and install Nix packages. For
|
||||
example, you should be able to successfully run a command like
|
||||
`nix-instantiate '<nixpkgs>' -A hello` without having to switch to the
|
||||
root user. For a multi-user install of Nix this means that your user
|
||||
must be covered by the {nix-allowed-users}[`allowed-users`] Nix
|
||||
option. On NixOS you can control this option using the
|
||||
{nixos-allowed-users}[`nix.allowedUsers`] system option.
|
||||
|
||||
2. Add the Home Manager channel that you wish to follow. If you are
|
||||
following Nixpkgs master or an unstable channel then this is done by
|
||||
running
|
||||
+
|
||||
[source,console]
|
||||
----
|
||||
$ nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager
|
||||
$ nix-channel --update
|
||||
----
|
||||
+
|
||||
and if you follow a Nixpkgs version 20.09 channel, you can run
|
||||
+
|
||||
[source,console]
|
||||
----
|
||||
$ nix-channel --add https://github.com/nix-community/home-manager/archive/release-20.09.tar.gz home-manager
|
||||
$ nix-channel --update
|
||||
----
|
||||
+
|
||||
On NixOS you may need to log out and back in for the channel to become
|
||||
available. On non-NixOS you may have to add
|
||||
+
|
||||
[source,bash]
|
||||
export NIX_PATH=$HOME/.nix-defexpr/channels${NIX_PATH:+:}$NIX_PATH
|
||||
+
|
||||
to your shell (see
|
||||
https://github.com/NixOS/nix/issues/2033[nix#2033]).
|
||||
|
||||
3. Run the Home Manager installation command and create the first Home
|
||||
Manager generation:
|
||||
+
|
||||
[source,console]
|
||||
$ nix-shell '<home-manager>' -A install
|
||||
+
|
||||
Once finished, Home Manager should be active and available in your
|
||||
user environment.
|
||||
|
||||
4. If you do not plan on having Home Manager manage your shell
|
||||
configuration then you must source the
|
||||
+
|
||||
[source,bash]
|
||||
$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh
|
||||
+
|
||||
file in your shell configuration. Alternatively source
|
||||
+
|
||||
[source,bash]
|
||||
/etc/profiles/per-user/$USER/etc/profile.d/hm-session-vars.sh
|
||||
+
|
||||
when managing home configuration together with system configuration.
|
||||
+
|
||||
Unfortunately, we currently only support POSIX.2-like shells such as
|
||||
https://www.gnu.org/software/bash/[Bash] or
|
||||
http://zsh.sourceforge.net/[Z shell].
|
||||
+
|
||||
For example, if you use Bash then add
|
||||
+
|
||||
[source,bash]
|
||||
----
|
||||
. "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh"
|
||||
----
|
||||
+
|
||||
to your `~/.profile` file.
|
||||
|
||||
If instead of using channels you want to run Home Manager from a Git
|
||||
checkout of the repository then you can use the
|
||||
<<opt-programs.home-manager.path>> option to specify the absolute path
|
||||
to the repository.
|
||||
|
||||
[[sec-install-nixos-module]]
|
||||
=== NixOS module
|
||||
|
||||
Home Manager provides a NixOS module that allows you to prepare user
|
||||
environments directly from the system configuration file, which often
|
||||
is more convenient than using the `home-manager` tool. It also opens
|
||||
up additional possibilities, for example, to automatically configure
|
||||
user environments in NixOS declarative containers or on systems
|
||||
deployed through NixOps.
|
||||
|
||||
To make the NixOS module available for use you must `import` it into
|
||||
your system configuration. This is most conveniently done by adding a
|
||||
Home Manager channel. For example, if you are following Nixpkgs master
|
||||
or an unstable channel, you can run
|
||||
|
||||
[source,console]
|
||||
----
|
||||
# nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager
|
||||
# nix-channel --update
|
||||
----
|
||||
|
||||
and if you follow a Nixpkgs version 20.09 channel, you can run
|
||||
|
||||
[source,console]
|
||||
----
|
||||
# nix-channel --add https://github.com/nix-community/home-manager/archive/release-20.09.tar.gz home-manager
|
||||
# nix-channel --update
|
||||
----
|
||||
|
||||
It is then possible to add
|
||||
|
||||
[source,nix]
|
||||
imports = [ <home-manager/nixos> ];
|
||||
|
||||
to your system `configuration.nix` file, which will introduce a new
|
||||
NixOS option called `home-manager.users` whose type is an attribute
|
||||
set that maps user names to Home Manager configurations.
|
||||
|
||||
For example, a NixOS configuration may include the lines
|
||||
|
||||
[source,nix]
|
||||
----
|
||||
users.users.eve.isNormalUser = true;
|
||||
home-manager.users.eve = { pkgs, ... }: {
|
||||
home.packages = [ pkgs.atool pkgs.httpie ];
|
||||
programs.bash.enable = true;
|
||||
};
|
||||
----
|
||||
|
||||
and after a `nixos-rebuild switch` the user eve's environment should
|
||||
include a basic Bash configuration and the packages atool and httpie.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
By default packages will be installed to `$HOME/.nix-profile` but they
|
||||
can be installed to `/etc/profiles` if
|
||||
|
||||
[source,nix]
|
||||
home-manager.useUserPackages = true;
|
||||
|
||||
is added to the system configuration. This is necessary if, for
|
||||
example, you wish to use `nixos-rebuild build-vm`. This option may
|
||||
become the default value in the future.
|
||||
====
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
By default, Home Manager uses a private `pkgs` instance that is
|
||||
configured via the `home-manager.users.<name>.nixpkgs` options. To
|
||||
instead use the global `pkgs` that is configured via the system level
|
||||
`nixpkgs` options, set
|
||||
|
||||
[source,nix]
|
||||
home-manager.useGlobalPkgs = true;
|
||||
|
||||
This saves an extra Nixpkgs evaluation, adds consistency, and removes
|
||||
the dependency on `NIX_PATH`, which is otherwise used for importing
|
||||
Nixpkgs.
|
||||
====
|
||||
|
||||
[[sec-install-nix-darwin-module]]
|
||||
=== nix-darwin module
|
||||
|
||||
Home Manager provides a module that allows you to prepare user
|
||||
environments directly from the {nix-darwin}[nix-darwin] configuration
|
||||
file, which often is more convenient than using the `home-manager`
|
||||
tool.
|
||||
|
||||
To make the NixOS module available for use you must `import` it into
|
||||
your system configuration. This is most conveniently done by adding a
|
||||
Home Manager channel. For example, if you are following Nixpkgs master
|
||||
or an unstable channel, you can run
|
||||
|
||||
[source,console]
|
||||
----
|
||||
# nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager
|
||||
# nix-channel --update
|
||||
----
|
||||
|
||||
and if you follow a Nixpkgs version 20.09 channel, you can run
|
||||
|
||||
[source,console]
|
||||
----
|
||||
# nix-channel --add https://github.com/nix-community/home-manager/archive/release-20.09.tar.gz home-manager
|
||||
# nix-channel --update
|
||||
----
|
||||
|
||||
It is then possible to add
|
||||
|
||||
[source,nix]
|
||||
imports = [ <home-manager/nix-darwin> ];
|
||||
|
||||
to your nix-darwin `configuration.nix` file, which will introduce a
|
||||
new NixOS option called `home-manager` whose type is an attribute set
|
||||
that maps user names to Home Manager configurations.
|
||||
|
||||
For example, a nix-darwin configuration may include the lines
|
||||
|
||||
[source,nix]
|
||||
----
|
||||
home-manager.users.eve = { pkgs, ... }: {
|
||||
home.packages = [ pkgs.atool pkgs.httpie ];
|
||||
programs.bash.enable = true;
|
||||
};
|
||||
----
|
||||
|
||||
and after a `darwin-rebuild switch` the user eve's environment
|
||||
should include a basic Bash configuration and the packages atool and
|
||||
httpie.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
By default user packages will not be ignored in favor of
|
||||
`environment.systemPackages`, but they will be intalled to
|
||||
`/etc/profiles/per-user/$USERNAME` if
|
||||
|
||||
[source,nix]
|
||||
home-manager.useUserPackages = true;
|
||||
|
||||
is added to the nix-darwin configuration. This option may become the
|
||||
default value in the future.
|
||||
====
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
By default, Home Manager uses a private `pkgs` instance that is
|
||||
configured via the `home-manager.users.<name>.nixpkgs` options. To
|
||||
instead use the global `pkgs` that is configured via the system level
|
||||
`nixpkgs` options, set
|
||||
|
||||
[source,nix]
|
||||
home-manager.useGlobalPkgs = true;
|
||||
|
||||
This saves an extra Nixpkgs evaluation, adds consistency, and removes
|
||||
the dependency on `NIX_PATH`, which is otherwise used for importing
|
||||
Nixpkgs.
|
||||
====
|
||||
40
doc/man-configuration.xml
Normal file
40
doc/man-configuration.xml
Normal file
@@ -0,0 +1,40 @@
|
||||
<refentry xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<refmeta>
|
||||
<refentrytitle><filename>home-configuration.nix</filename></refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
<refmiscinfo class="source">Home Manager</refmiscinfo>
|
||||
<!-- <refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo> -->
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname><filename>home-configuration.nix</filename></refname>
|
||||
<refpurpose>Home Manager configuration specification</refpurpose>
|
||||
</refnamediv>
|
||||
<refsection>
|
||||
<title>Description</title>
|
||||
<para>
|
||||
The file <filename>~/.config/nixpkgs/home.nix</filename> contains the
|
||||
declarative specification of your Home Manager configuration. The command
|
||||
<command>home-manager</command> takes this file and realises the user
|
||||
environment configuration specified therein.
|
||||
</para>
|
||||
</refsection>
|
||||
<refsection>
|
||||
<title>Options</title>
|
||||
<para>
|
||||
You can use the following options in
|
||||
<filename>home-configuration.nix</filename>:
|
||||
</para>
|
||||
<xi:include href="./nmd-result/home-manager-options.xml" />
|
||||
</refsection>
|
||||
<refsection>
|
||||
<title>See also</title>
|
||||
<para>
|
||||
<citerefentry>
|
||||
<refentrytitle>home-manager</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry>
|
||||
</para>
|
||||
</refsection>
|
||||
</refentry>
|
||||
555
doc/man-home-manager.xml
Normal file
555
doc/man-home-manager.xml
Normal file
@@ -0,0 +1,555 @@
|
||||
<refentry xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<refmeta>
|
||||
<refentrytitle><command>home-manager</command>
|
||||
</refentrytitle><manvolnum>1</manvolnum>
|
||||
<refmiscinfo class="source">Home Manager</refmiscinfo>
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname><command>home-manager</command>
|
||||
</refname><refpurpose>reconfigure a user environment</refpurpose>
|
||||
</refnamediv>
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>home-manager</command> <group choice="req">
|
||||
<arg choice="plain">
|
||||
build
|
||||
</arg>
|
||||
|
||||
<arg choice="plain">
|
||||
instantiate
|
||||
</arg>
|
||||
|
||||
<arg choice="plain">
|
||||
edit
|
||||
</arg>
|
||||
|
||||
<arg choice="plain">
|
||||
expire-generations <replaceable>timestamp</replaceable>
|
||||
</arg>
|
||||
|
||||
<arg choice="plain">
|
||||
generations
|
||||
</arg>
|
||||
|
||||
<arg choice="plain">
|
||||
help
|
||||
</arg>
|
||||
|
||||
<arg choice="plain">
|
||||
news
|
||||
</arg>
|
||||
|
||||
<arg choice="plain">
|
||||
packages
|
||||
</arg>
|
||||
|
||||
<arg choice="plain">
|
||||
remove-generations <replaceable>ID …</replaceable>
|
||||
</arg>
|
||||
|
||||
<arg choice="plain">
|
||||
switch
|
||||
</arg>
|
||||
|
||||
<arg choice="plain">
|
||||
uninstall
|
||||
</arg>
|
||||
</group>
|
||||
<sbr />
|
||||
<arg>
|
||||
-A <replaceable>attrPath</replaceable>
|
||||
</arg>
|
||||
|
||||
<arg>
|
||||
-I <replaceable>path</replaceable>
|
||||
</arg>
|
||||
|
||||
<arg>
|
||||
--flake <replaceable>flake-uri</replaceable>
|
||||
</arg>
|
||||
|
||||
<arg>
|
||||
-b <replaceable>ext</replaceable>
|
||||
</arg>
|
||||
|
||||
<arg>
|
||||
<group choice="req">
|
||||
<arg choice="plain">
|
||||
-f
|
||||
</arg>
|
||||
|
||||
<arg choice="plain">
|
||||
--file
|
||||
</arg>
|
||||
</group> <replaceable>path</replaceable>
|
||||
</arg>
|
||||
|
||||
<arg>
|
||||
<group choice="req">
|
||||
<arg choice="plain">
|
||||
-h
|
||||
</arg>
|
||||
|
||||
<arg choice="plain">
|
||||
--help
|
||||
</arg>
|
||||
</group>
|
||||
</arg>
|
||||
|
||||
<arg>
|
||||
<group choice="req">
|
||||
<arg choice="plain">
|
||||
-n
|
||||
</arg>
|
||||
|
||||
<arg choice="plain">
|
||||
--dry-run
|
||||
</arg>
|
||||
</group>
|
||||
</arg>
|
||||
|
||||
<arg>
|
||||
--option <replaceable>name</replaceable> <replaceable>value</replaceable>
|
||||
</arg>
|
||||
|
||||
<arg>
|
||||
--cores <replaceable>number</replaceable>
|
||||
</arg>
|
||||
|
||||
<arg>
|
||||
<group choice="req">
|
||||
<arg choice="plain">
|
||||
-j
|
||||
</arg>
|
||||
|
||||
<arg choice="plain">
|
||||
--max-jobs
|
||||
</arg>
|
||||
</group>
|
||||
<replaceable>number</replaceable>
|
||||
</arg>
|
||||
|
||||
<arg>
|
||||
--keep-failed
|
||||
</arg>
|
||||
|
||||
<arg>
|
||||
--keep-going
|
||||
</arg>
|
||||
|
||||
<arg>
|
||||
--show-trace
|
||||
</arg>
|
||||
|
||||
<arg>
|
||||
--(no-)substitute
|
||||
</arg>
|
||||
|
||||
<arg>
|
||||
<group choice="req">
|
||||
<arg choice="plain">
|
||||
-v
|
||||
</arg>
|
||||
|
||||
<arg choice="plain">
|
||||
--verbose
|
||||
</arg>
|
||||
</group>
|
||||
</arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
<refsection>
|
||||
<title>Description</title>
|
||||
<para>
|
||||
This command updates the user environment so that it corresponds to the
|
||||
configuration specified in <filename>~/.config/nixpkgs/home.nix</filename> or <filename>~/.config/nixpkgs/flake.nix</filename>.
|
||||
</para>
|
||||
<para>
|
||||
All operations using this tool expects a sub-command that indicates the
|
||||
operation to perform. It must be one of
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>build</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Build configuration into a <filename>result</filename> directory.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>instantiate</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Instantiate the configuration and print the resulting derivation.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>edit</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Open the home configuration using the editor indicated by
|
||||
<envar>EDITOR</envar>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>expire-generations <replaceable>timestamp</replaceable></option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Remove generations older than <replaceable>timestamp</replaceable> where
|
||||
<replaceable>timestamp</replaceable> is interpreted as in the
|
||||
<option>-d</option> argument of the <citerefentry>
|
||||
<refentrytitle>date</refentrytitle>
|
||||
<manvolnum>1</manvolnum> </citerefentry> tool. For example <literal>-30
|
||||
days</literal> or <literal>2018-01-01</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>generations</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
List all home environment generations.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>help</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Print tool help.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>news</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Show news entries in a pager.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>packages</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
List all packages installed in <varname>home-manager-path</varname>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>remove-generations <replaceable>ID …</replaceable></option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Remove indicated generations. Use the <option>generations</option>
|
||||
sub-command to find suitable generation numbers.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>switch</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Build and activate the configuration.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>uninstall</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Remove Home Manager from the user environment. This will
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
remove all managed files from the home directory,
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
remove packages installed through Home Manager from the user profile,
|
||||
and
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
optionally remove all Home Manager generations and make them
|
||||
available for immediate garbage collection.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
</refsection>
|
||||
<refsection>
|
||||
<title>Options</title>
|
||||
<para>
|
||||
The tool accepts the options
|
||||
</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>-A <replaceable>attrPath</replaceable></option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Optional attribute that selects a configuration expression in the
|
||||
configuration file. That is, if <filename>home.nix</filename> contains
|
||||
<programlisting language="nix">
|
||||
{
|
||||
joe-at-work = {pkgs, ...}: { home.packages = [ pkgs.fortune ]; };
|
||||
joe-at-home = {pkgs, ...}: { home.packages = [ pkgs.cowsay ]; };
|
||||
}
|
||||
</programlisting>
|
||||
then the command <command>home-manager switch -A joe-at-work</command>
|
||||
will activate the profile containing the fortune program.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>-I <replaceable>path</replaceable></option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Add a path to the Nix expression search path. For example, to build a
|
||||
Home Manager profile using a specific Nixpkgs run <command>home-manager
|
||||
-I nixpkgs=/absolute/path/to/nixpkgs build</command>. By default
|
||||
<literal><nixpkgs></literal> is used.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--flake <replaceable>flake-uri[#name]</replaceable></option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Build Home Manager configuration from the flake, which must contain the
|
||||
output homeConfigurations.name. If no name is specified it will first try
|
||||
username@hostname and then username.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>-b <replaceable>extension</replaceable></option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Enable automatic resolution of collisions between unmanaged and managed
|
||||
files. The name of the original file will be suffixed by the given
|
||||
extension. For example,
|
||||
<screen>
|
||||
<prompt>$</prompt> <userinput>home-manager -b bck switch</userinput>
|
||||
</screen>
|
||||
will cause a colliding file <filename>~/.config/foo.conf</filename> to be
|
||||
moved to <filename>~/.config/foo.conf.bck</filename>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>-f <replaceable>path</replaceable></option>
|
||||
</term>
|
||||
<term>
|
||||
<option>--file <replaceable>path</replaceable></option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Indicates the path to the Home Manager configuration file. If not given,
|
||||
<filename>~/.config/nixpkgs/home.nix</filename> is used.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>-h</option>
|
||||
</term>
|
||||
<term>
|
||||
<option>--help</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Prints usage information for the <command>home-manager</command> tool.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>-n</option>
|
||||
</term>
|
||||
<term>
|
||||
<option>--dry-run</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Perform a dry-run of the given operation, only prints what actions would
|
||||
be taken.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--option <replaceable>name</replaceable> <replaceable>value</replaceable></option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Passed on to <citerefentry>
|
||||
<refentrytitle>nix-build</refentrytitle>
|
||||
<manvolnum>1</manvolnum> </citerefentry>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--cores <replaceable>number</replaceable></option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Passed on to <citerefentry>
|
||||
<refentrytitle>nix-build</refentrytitle>
|
||||
<manvolnum>1</manvolnum> </citerefentry>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>-j <replaceable>number</replaceable></option>
|
||||
</term>
|
||||
<term>
|
||||
<option>--max-jobs <replaceable>number</replaceable></option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Passed on to <citerefentry>
|
||||
<refentrytitle>nix-build</refentrytitle>
|
||||
<manvolnum>1</manvolnum> </citerefentry>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--keep-failed</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Passed on to <citerefentry>
|
||||
<refentrytitle>nix-build</refentrytitle>
|
||||
<manvolnum>1</manvolnum> </citerefentry>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--keep-going</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Passed on to <citerefentry>
|
||||
<refentrytitle>nix-build</refentrytitle>
|
||||
<manvolnum>1</manvolnum> </citerefentry>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--show-trace</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Passed on to <citerefentry>
|
||||
<refentrytitle>nix-build</refentrytitle>
|
||||
<manvolnum>1</manvolnum> </citerefentry>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--(no-)substitute</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Passed on to <citerefentry>
|
||||
<refentrytitle>nix-build</refentrytitle>
|
||||
<manvolnum>1</manvolnum> </citerefentry>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>-v</option>
|
||||
</term>
|
||||
<term>
|
||||
<option>--verbose</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Activates verbose output.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsection>
|
||||
<refsection>
|
||||
<title>Files</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<filename>~/.local/share/home-manager/news-read-ids</filename>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Identifiers of news items that have been shown. Can be deleted to reset
|
||||
the read news indicator.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsection>
|
||||
<refsection>
|
||||
<title>Bugs</title>
|
||||
<para>
|
||||
Please report any bugs on the
|
||||
<link
|
||||
xlink:href="https://github.com/nix-community/home-manager/issues">project
|
||||
issue tracker</link>.
|
||||
</para>
|
||||
</refsection>
|
||||
<refsection>
|
||||
<title>See also</title>
|
||||
<para>
|
||||
<citerefentry>
|
||||
<refentrytitle>home-configuration.nix</refentrytitle>
|
||||
<manvolnum>5</manvolnum> </citerefentry>
|
||||
</para>
|
||||
</refsection>
|
||||
</refentry>
|
||||
12
doc/man-pages.xml
Normal file
12
doc/man-pages.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<reference xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<title>Home Manager Reference Pages</title>
|
||||
<info>
|
||||
<author><personname>Home Manager contributors</personname></author>
|
||||
<copyright><year>2017–2020</year><holder>Home Manager contributors</holder>
|
||||
</copyright>
|
||||
</info>
|
||||
<xi:include href="man-configuration.xml" />
|
||||
<xi:include href="man-home-manager.xml" />
|
||||
</reference>
|
||||
54
doc/manual.xml
Normal file
54
doc/manual.xml
Normal file
@@ -0,0 +1,54 @@
|
||||
<book xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="book-home-manager-manual">
|
||||
<info>
|
||||
<title>Home Manager Manual</title>
|
||||
</info>
|
||||
<preface>
|
||||
<title>Preface</title>
|
||||
<para>
|
||||
This manual will eventually describes how to install, use, and extend Home
|
||||
Manager.
|
||||
</para>
|
||||
<para>
|
||||
If you encounter problems then please reach out on the IRC channel
|
||||
<link xlink:href="https://webchat.freenode.net/?url=irc%3A%2F%2Firc.freenode.net%2Fhome-manager">#home-manager</link>
|
||||
hosted by <link xlink:href="https://freenode.net/">freenode</link>.
|
||||
The <link xlink:href="https://logs.nix.samueldr.com/home-manager/">channel logs</link>
|
||||
are hosted courtesy of <link xlink:href="https://github.com/samueldr/">samueldr</link>.
|
||||
If your problem is caused by a bug in Home Manager then it should
|
||||
be reported on the
|
||||
<link xlink:href="https://github.com/nix-community/home-manager/issues">Home Manager issue tracker</link>.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
Commands prefixed with <literal>#</literal> have to be run as root, either
|
||||
requiring to login as root user or temporarily switching to it using
|
||||
<literal>sudo</literal> for example.
|
||||
</para>
|
||||
</note>
|
||||
</preface>
|
||||
<xi:include href="installation.xml" />
|
||||
<xi:include href="writing-modules.xml" />
|
||||
<xi:include href="contributing.xml" />
|
||||
<xi:include href="faq.xml" />
|
||||
<appendix xml:id="ch-options">
|
||||
<title>Configuration Options</title>
|
||||
<xi:include href="./nmd-result/home-manager-options.xml" />
|
||||
</appendix>
|
||||
<appendix xml:id="ch-nixos-options">
|
||||
<title>NixOS Module Options</title>
|
||||
<xi:include href="./nmd-result/nixos-options.xml" />
|
||||
</appendix>
|
||||
<appendix xml:id="ch-nix-darwin-options">
|
||||
<title>nix-darwin Module Options</title>
|
||||
<xi:include href="./nmd-result/nix-darwin-options.xml" />
|
||||
</appendix>
|
||||
<appendix xml:id="ch-tools">
|
||||
<title>Tools</title>
|
||||
<xi:include href="./man-home-manager.xml" />
|
||||
</appendix>
|
||||
<xi:include href="./release-notes/release-notes.xml" />
|
||||
</book>
|
||||
21
doc/release-notes/release-notes.adoc
Normal file
21
doc/release-notes/release-notes.adoc
Normal file
@@ -0,0 +1,21 @@
|
||||
[[ch-release-notes]]
|
||||
[appendix]
|
||||
== Release Notes
|
||||
|
||||
This section lists the release notes for stable versions of Home Manager and the current unstable version.
|
||||
|
||||
:leveloffset: 1
|
||||
|
||||
include::rl-2105.adoc[]
|
||||
|
||||
include::rl-2009.adoc[]
|
||||
|
||||
include::rl-2003.adoc[]
|
||||
|
||||
include::rl-1909.adoc[]
|
||||
|
||||
include::rl-1903.adoc[]
|
||||
|
||||
include::rl-1809.adoc[]
|
||||
|
||||
:leveloffset: 0
|
||||
4
doc/release-notes/rl-1809.adoc
Normal file
4
doc/release-notes/rl-1809.adoc
Normal file
@@ -0,0 +1,4 @@
|
||||
[[sec-release-18.09]]
|
||||
== Release 18.09
|
||||
|
||||
The 18.09 release branch became the stable branch in September, 2018.
|
||||
59
doc/release-notes/rl-1903.adoc
Normal file
59
doc/release-notes/rl-1903.adoc
Normal file
@@ -0,0 +1,59 @@
|
||||
[[sec-release-19.03]]
|
||||
== Release 19.03
|
||||
|
||||
The 19.03 release branch became the stable branch in April, 2019.
|
||||
|
||||
[[sec-release-19.03-highlights]]
|
||||
=== Highlights
|
||||
:opt-home-file-source: opt-home.file._name_.source
|
||||
|
||||
This release has the following notable changes:
|
||||
|
||||
* The <<{opt-home-file-source}>> option now allows source files to be
|
||||
hidden, that is, having a name starting with the `.` character. It
|
||||
also allows the source file name to contain characters not typically
|
||||
allowed for Nix store paths. For example, your configuration can now
|
||||
contain things such as
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
home.file."my file".source = ./. + "/file with spaces!";
|
||||
----
|
||||
|
||||
* The type used for the systemd unit options under
|
||||
<<opt-systemd.user.services>>, <<opt-systemd.user.sockets>>, etc. has
|
||||
been changed to offer more robust merging of configurations. If you
|
||||
don't override values within systemd units then you are not affected
|
||||
by this change. Unfortunately, if you do override unit values you may
|
||||
encounter errors.
|
||||
+
|
||||
In particular, if you get an error saying that a ``unique option'' is
|
||||
``defined multiple times'' then you need to use the
|
||||
https://nixos.org/nixos/manual/#sec-option-definitions-setting-priorities[`mkForce`]
|
||||
function. For example,
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
systemd.user.services.foo.Service.ExecStart = "/foo/bar";
|
||||
----
|
||||
+
|
||||
becomes
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
systemd.user.services.foo.Service.ExecStart = lib.mkForce "/foo/bar";
|
||||
----
|
||||
+
|
||||
We had to make this change because the old merging was causing too
|
||||
many confusing situations for people.
|
||||
|
||||
[[sec-release-19.03-state-version-changes]]
|
||||
=== State Version Changes
|
||||
|
||||
The state version in this release includes the changes below. These
|
||||
changes are only active if the <<opt-home.stateVersion>> option is set
|
||||
to ``19.03'' or later.
|
||||
|
||||
* There is now an option <<opt-programs.beets.enable>> that defaults
|
||||
to `false`. Before the module would be active if the
|
||||
<<opt-programs.beets.settings>> option was non-empty.
|
||||
31
doc/release-notes/rl-1909.adoc
Normal file
31
doc/release-notes/rl-1909.adoc
Normal file
@@ -0,0 +1,31 @@
|
||||
[[sec-release-19.09]]
|
||||
== Release 19.09
|
||||
|
||||
The 19.09 release branch became the stable branch in October, 2019.
|
||||
|
||||
[[sec-release-19.09-highlights]]
|
||||
=== Highlights
|
||||
|
||||
This release has the following notable changes:
|
||||
|
||||
* The `programs.firefox.enableGoogleTalk` and
|
||||
`programs.firefox.enableIcedTea` options are now deprecated
|
||||
and will only work if Firefox ESR 52.x is used.
|
||||
|
||||
* The `home-manager` tool now provides an `uninstall` sub-command that
|
||||
can be used to uninstall Home Manager, if used in the standalone
|
||||
mode. That is, not as a NixOS module.
|
||||
|
||||
[[sec-release-19.09-state-version-changes]]
|
||||
=== State Version Changes
|
||||
|
||||
The state version in this release includes the changes below. These
|
||||
changes are only active if the `home.stateVersion` option is set to
|
||||
"19.09" or later.
|
||||
|
||||
* The <<opt-programs.firefox.package>> option now expects a wrapped
|
||||
Firefox package and defaults to `pkgs.firefox`.
|
||||
|
||||
* The options <<opt-home.keyboard.layout>> and
|
||||
<<opt-home.keyboard.variant>> now default to `null`, which indicates
|
||||
that the system value should be used.
|
||||
126
doc/release-notes/rl-2003.adoc
Normal file
126
doc/release-notes/rl-2003.adoc
Normal file
@@ -0,0 +1,126 @@
|
||||
[[sec-release-20.03]]
|
||||
== Release 20.03
|
||||
|
||||
The 20.03 release branch became the stable branch in April, 2020.
|
||||
|
||||
[[sec-release-20.03-highlights]]
|
||||
=== Highlights
|
||||
|
||||
This release has the following notable changes:
|
||||
|
||||
* Assigning a list to the <<opt-home.file>>, <<opt-xdg.configFile>>,
|
||||
and <<opt-xdg.dataFile>> options is now deprecated and will produce a
|
||||
warning message if used. Specifically, if your configuration currently
|
||||
contains something like
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
home.file = [
|
||||
{
|
||||
target = ".config/foo.txt";
|
||||
text = "bar";
|
||||
}
|
||||
]
|
||||
----
|
||||
+
|
||||
then it should be updated to instead use the equivalent attribute set form
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
home.file = {
|
||||
".config/foo.txt".text = "bar";
|
||||
}
|
||||
----
|
||||
+
|
||||
Support for the list form will be removed in Home Manager version
|
||||
20.09.
|
||||
|
||||
* The `lib` function attribute given to modules is now enriched with
|
||||
an attribute `hm` containing extra library functions specific for Home
|
||||
Manager. More specifically, `lib.hm` is now the same as `config.lib`
|
||||
and should be the preferred choice since it is more robust.
|
||||
+
|
||||
Therefore, if your configuration makes use of, for example,
|
||||
`config.lib.dag` to create activation script blocks, it is recommended
|
||||
to change to `lib.hm.dag`.
|
||||
+
|
||||
Note, in the unlikely case that you are
|
||||
+
|
||||
** using Home Manager's NixOS or nix-darwin module,
|
||||
** have made your own Home Manager module containing an top-level
|
||||
option named `config` or `options`, and
|
||||
** assign to this option in your system configuration inside a plain
|
||||
attribute set, i.e., without a function argument,
|
||||
|
||||
+
|
||||
then you must update your configuration to perform the option
|
||||
assignment inside a `config` attribute. For example, instead of
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
home-manager.users.jane = { config = "foo"; };
|
||||
----
|
||||
+
|
||||
use
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
home-manager.users.jane = { config.config = "foo"; };
|
||||
----
|
||||
|
||||
* The `services.compton` module has been deprecated and instead the
|
||||
new module `services.picom` should be used. This is because Nixpkgs no
|
||||
longer packages compton, and instead packages the (mostly) compatible
|
||||
fork called picom.
|
||||
|
||||
* The list form of the <<opt-programs.ssh.matchBlocks>> option has
|
||||
been deprecated and configurations requiring match blocks in a defined
|
||||
order should switch to using DAG entries instead. For example, a
|
||||
configuration
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
programs.ssh.matchBlocks = [
|
||||
{
|
||||
host = "alpha.foo.com";
|
||||
user = "jd";
|
||||
}
|
||||
{
|
||||
host = "*.foo.com";
|
||||
user = "john.doe";
|
||||
}
|
||||
];
|
||||
----
|
||||
+
|
||||
can be expressed along the lines of
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
programs.ssh.matchBlocks = {
|
||||
"*.example.com" = {
|
||||
user = "john.doe";
|
||||
}
|
||||
"alpha.example.com" = lib.hm.dag.entryBefore ["*.example.com"] {
|
||||
user = "jd";
|
||||
}
|
||||
};
|
||||
----
|
||||
+
|
||||
Support for the list form will be removed in Home Manager version
|
||||
20.09.
|
||||
|
||||
[[sec-release-20.03-state-version-changes]]
|
||||
=== State Version Changes
|
||||
|
||||
The state version in this release includes the changes below. These
|
||||
changes are only active if the `home.stateVersion` option is set to
|
||||
"20.03" or later.
|
||||
|
||||
* The <<opt-programs.zsh.history.path>> option is no longer prepended
|
||||
by `$HOME`, which allows specifying absolute paths, for example,
|
||||
using the xdg module. Also, the default value is fixed to
|
||||
`$HOME/.zsh_history` and `dotDir` path is not prepended to it
|
||||
anymore.
|
||||
* The newsboat module will now default in displaying `queries` before `urls` in
|
||||
its main window. This makes sense in the case when one has a lot of URLs and
|
||||
few queries.
|
||||
96
doc/release-notes/rl-2009.adoc
Normal file
96
doc/release-notes/rl-2009.adoc
Normal file
@@ -0,0 +1,96 @@
|
||||
[[sec-release-20.09]]
|
||||
== Release 20.09
|
||||
|
||||
The 20.09 release branch became the stable branch in late September, 2020.
|
||||
|
||||
[[sec-release-20.09-highlights]]
|
||||
=== Highlights
|
||||
|
||||
This release has the following notable changes:
|
||||
|
||||
* Nothing has happened.
|
||||
|
||||
[[sec-release-20.09-state-version-changes]]
|
||||
=== State Version Changes
|
||||
|
||||
The state version in this release includes the changes below. These
|
||||
changes are only active if the `home.stateVersion` option is set to
|
||||
"20.09" or later.
|
||||
|
||||
* The options <<opt-home.homeDirectory>> and <<opt-home.username>> no
|
||||
longer have default values and must therefore be provided in your
|
||||
configuration. Previously their values would default to the content of
|
||||
the environment variables `HOME` and `USER`, respectively.
|
||||
+
|
||||
--
|
||||
Further, the options <<opt-xdg.cacheHome>>, <<opt-xdg.configHome>>,
|
||||
and <<opt-xdg.dataHome>> will no longer be affected by the
|
||||
`XDG_CACHE_HOME`, `XDG_CONFIG_HOME`, and `XDG_DATA_HOME` environment
|
||||
variables. They now unconditionally default to
|
||||
|
||||
- `"${config.home.homeDirectory}/.cache"`,
|
||||
- `"${config.home.homeDirectory}/.config"`, and
|
||||
- `"${config.home.homeDirectory}/.local/share"`.
|
||||
|
||||
If you choose to switch to state version 20.09 then you must set these
|
||||
options if you use non-default XDG base directory paths.
|
||||
|
||||
The initial configuration generated by
|
||||
|
||||
[source,console]
|
||||
$ nix-shell '<home-manager>' -A install
|
||||
|
||||
will automatically include these options, when necessary.
|
||||
--
|
||||
|
||||
* Git's `smtpEncryption` option is now set to `tls` only if both <<opt-accounts.email.accounts.\_name_.smtp.tls.enable>> and <<opt-accounts.email.accounts.\_name_.smtp.tls.useStartTls>> are `true`. If only <<opt-accounts.email.accounts.\_name_.smtp.tls.enable>> is `true`, `ssl` is used instead.
|
||||
|
||||
* The `nixpkgs` module no longer references `<nixpkgs>`. Before it would do so when building the `pkgs` module argument. Starting with state version 20.09, the `pkgs` argument is instead built from the same Nixpkgs that was used to initialize the Home Manager modules. This is useful, for example, when using Home Manager within a Nix Flake. If you want to keep using `<nixpkgs>` with state version ≥ 20.09 then add
|
||||
+
|
||||
[source,nix]
|
||||
_module.args.pkgsPath = <nixpkgs>;
|
||||
+
|
||||
to your Home Manager configuration.
|
||||
|
||||
* The options `wayland.windowManager.sway.config.bars` and `opt-xsession.windowManager.i3.config.bars` have been changed so that most of the suboptions are now nullable and default to `null`. The default for these two options has been changed to manually set the old defaults for each suboption. The overall effect is that if the `bars` options is not set, then the default remains the same. On the other hand, something like:
|
||||
+
|
||||
--
|
||||
[source,nix]
|
||||
----
|
||||
bars = [ {
|
||||
command = "waybar";
|
||||
} ];
|
||||
----
|
||||
will now create the config:
|
||||
....
|
||||
bar {
|
||||
swaybar_command waybar
|
||||
}
|
||||
....
|
||||
instead of
|
||||
....
|
||||
bar {
|
||||
|
||||
font pango:monospace 8
|
||||
mode dock
|
||||
hidden_state hide
|
||||
position bottom
|
||||
status_command /nix/store/h7s6i9q1z5fxrlyyw5ls8vqxhf5bcs5a-i3status-2.13/bin/i3status
|
||||
swaybar_command waybar
|
||||
workspace_buttons yes
|
||||
strip_workspace_numbers no
|
||||
tray_output primary
|
||||
colors {
|
||||
background #000000
|
||||
statusline #ffffff
|
||||
separator #666666
|
||||
focused_workspace #4c7899 #285577 #ffffff
|
||||
active_workspace #333333 #5f676a #ffffff
|
||||
inactive_workspace #333333 #222222 #888888
|
||||
urgent_workspace #2f343a #900000 #ffffff
|
||||
binding_mode #2f343a #900000 #ffffff
|
||||
}
|
||||
|
||||
}
|
||||
....
|
||||
--
|
||||
182
doc/release-notes/rl-2105.adoc
Normal file
182
doc/release-notes/rl-2105.adoc
Normal file
@@ -0,0 +1,182 @@
|
||||
[[sec-release-21.05]]
|
||||
== Release 21.05
|
||||
|
||||
This is the current unstable branch and the information in this
|
||||
section is therefore not final.
|
||||
|
||||
[[sec-release-21.05-highlights]]
|
||||
=== Highlights
|
||||
|
||||
This release has the following notable changes:
|
||||
|
||||
* The <<opt-programs.broot.verbs>> option is now a list rather than an
|
||||
attribute set. To migrate, move the keys of the attrset into the list
|
||||
items' `invocation` keys. For example,
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
programs.broot.verbs = {
|
||||
"p" = { execution = ":parent"; };
|
||||
};
|
||||
----
|
||||
+
|
||||
becomes
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
programs.broot.verbs = [
|
||||
{
|
||||
invocation = "p";
|
||||
execution = ":parent";
|
||||
}
|
||||
];
|
||||
----
|
||||
|
||||
* The <<opt-programs.mpv.package>> option has been changed to allow custom
|
||||
derivations. The following configuration is now possible:
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
programs.mpv.package = (pkgs.wrapMpv (pkgs.mpv-unwrapped.override {
|
||||
vapoursynthSupport = true;
|
||||
}) {
|
||||
extraMakeWrapperArgs = [
|
||||
"--prefix" "LD_LIBRARY_PATH" ":" "${pkgs.vapoursynth-mvtools}/lib/vapoursynth"
|
||||
];
|
||||
});
|
||||
----
|
||||
+
|
||||
As a result of this change, <<opt-programs.mpv.package>> is no longer the
|
||||
resulting derivation. Use the newly introduced `programs.mpv.finalPackage`
|
||||
instead.
|
||||
|
||||
* The <<opt-programs.rofi.extraConfig>> option is now an attribute set rather
|
||||
than a string. To migrate, move each line into the attribute set,
|
||||
removing the `rofi.` prefix from the keys. For example,
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
programs.rofi.extraConfig = ''
|
||||
rofi.show-icons: true
|
||||
rofi.modi: drun,emoji,ssh
|
||||
'';
|
||||
----
|
||||
+
|
||||
becomes
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
programs.rofi.extraConfig = {
|
||||
show-icons = true;
|
||||
modi = "drun,emoji,ssh";
|
||||
};
|
||||
----
|
||||
+
|
||||
* The <<opt-programs.rofi.theme>> option now supports defining a theme
|
||||
using an attribute set, the following configuration is now possible:
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
programs.rofi.theme = let
|
||||
# Necessary to avoid quoting non-string values
|
||||
inherit (config.lib.formats.rasi) mkLiteral;
|
||||
in {
|
||||
"@import" = "~/.config/rofi/theme.rasi";
|
||||
|
||||
"*" = {
|
||||
background-color = mkLiteral "#000000";
|
||||
foreground-color = mkLiteral "rgba ( 250, 251, 252, 100 % )";
|
||||
border-color = mkLiteral "#FFFFFF";
|
||||
width = 512;
|
||||
};
|
||||
|
||||
"#textbox-prompt-colon" = {
|
||||
expand = false;
|
||||
str = ":";
|
||||
margin = mkLiteral "0px 0.3em 0em 0em";
|
||||
text-color = mkLiteral "@foreground-color";
|
||||
};
|
||||
};
|
||||
----
|
||||
|
||||
|
||||
* The `services.redshift.extraOptions` and `services.gammastep.extraOptions`
|
||||
options were removed in favor of <<opt-services.redshift.settings>> and
|
||||
`services.gammastep.settings`, that are now an attribute set rather
|
||||
than a string. They also support new features not available before, for
|
||||
example:
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
services.redshift = {
|
||||
dawnTime = "6:00-7:45";
|
||||
duskTime = "18:35-20:15";
|
||||
settings = {
|
||||
redshift = {
|
||||
gamma = 0.8;
|
||||
adjustment-method = "randr";
|
||||
};
|
||||
|
||||
randr = {
|
||||
screen = 0;
|
||||
};
|
||||
};
|
||||
};
|
||||
----
|
||||
+
|
||||
It is recommended to check either
|
||||
https://github.com/jonls/redshift/blob/master/redshift.conf.sample[redshift.conf.sample] or
|
||||
https://gitlab.com/chinstrap/gammastep/-/blob/master/gammastep.conf.sample[gammastep.conf.sample]
|
||||
for the available additional options in each program.
|
||||
|
||||
* Specifying `programs.neomutt.binds.map` or `programs.neomutt.macros.map` as a
|
||||
single string is now deprecated in favor of specfiying it as a list of
|
||||
strings.
|
||||
|
||||
* The `programs.neovim.configure` is deprecated in favor of other `programs.neovim` options;
|
||||
please use the other options at your disposal:
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
configure.packages.*.opt -> programs.neovim.plugins = [ { plugin = ...; optional = true; }]
|
||||
configure.packages.*.start -> programs.neovim.plugins = [ { plugin = ...; }]
|
||||
configure.customRC -> programs.neovim.extraConfig
|
||||
----
|
||||
|
||||
* Home Manager now respects the `NO_COLOR` environment variable as per
|
||||
https://no-color.org/[].
|
||||
|
||||
* Qt module now supports <<opt-qt.style.name>> to specify a theme name and
|
||||
<<opt-qt.style.package>> to specify a theme package. If you have set
|
||||
<<opt-qt.platformTheme>> to `gnome`, a <<opt-qt.style.package>> compatible
|
||||
with both Qt and Gtk is now required to be set. For instance:
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
qt = {
|
||||
platformTheme = "gnome";
|
||||
style = {
|
||||
name = "adwaita-dark";
|
||||
package = pkgs.adwaita-qt;
|
||||
};
|
||||
};
|
||||
----
|
||||
|
||||
* The library type `fontType` now has a `size` attribute in addition to `name`. For example:
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
font = {
|
||||
name = "DejaVu Sans";
|
||||
size = 8;
|
||||
};
|
||||
----
|
||||
|
||||
[[sec-release-21.05-state-version-changes]]
|
||||
=== State Version Changes
|
||||
|
||||
The state version in this release includes the changes below. These
|
||||
changes are only active if the `home.stateVersion` option is set to
|
||||
"21.05" or later.
|
||||
|
||||
* Nothing has happened.
|
||||
187
doc/writing-modules.adoc
Normal file
187
doc/writing-modules.adoc
Normal file
@@ -0,0 +1,187 @@
|
||||
[[ch-writing-modules]]
|
||||
== Writing Home Manager Modules
|
||||
:writing-nixos-modules: https://nixos.org/nixos/manual/index.html#sec-writing-modules
|
||||
|
||||
The module system in Home Manager is based entirely on the NixOS module system so we will here only highlight aspects that are specific for Home Manager. For information about the module system as such please refer to the {writing-nixos-modules}[Writing NixOS Modules] chapter of the NixOS manual.
|
||||
|
||||
[[sec-option-types]]
|
||||
=== Option Types
|
||||
:wikipedia-dag: https://en.wikipedia.org/w/index.php?title=Directed_acyclic_graph&oldid=939656095
|
||||
:gvariant-description: https://developer.gnome.org/glib/stable/glib-GVariant.html#glib-GVariant.description
|
||||
|
||||
Overall the basic option types are the same in Home Manager as NixOS. A few Home Manager options, however, make use of custom types that are worth describing in more detail. These are the option types `dagOf` and `gvariant` that are used, for example, by <<opt-programs.ssh.matchBlocks>> and <<opt-dconf.settings>>.
|
||||
|
||||
`hm.types.dagOf`::
|
||||
Options of this type have attribute sets as values where each member is a node in a {wikipedia-dag}[directed acyclic graph] (DAG). This allows the attribute set entries to express dependency relations among themselves. This can, for example, be used to control the order of match blocks in a OpenSSH client configuration or the order of activation script blocks in <<opt-home.activation>>.
|
||||
+
|
||||
A number of functions are provided to create DAG nodes. The functions are shown below with examples using an option `foo.bar` of type `hm.types.dagOf types.int`.
|
||||
+
|
||||
`hm.dag.entryAnywhere (value: T)`:::
|
||||
Indicates that `value` can be placed anywhere within the DAG. This is also the default for plain attribute set entries, that is
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
foo.bar = {
|
||||
a = hm.dag.entryAnywhere 0;
|
||||
}
|
||||
----
|
||||
+
|
||||
and
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
foo.bar = {
|
||||
a = 0;
|
||||
}
|
||||
----
|
||||
+
|
||||
are equivalent.
|
||||
+
|
||||
`hm.dag.entryAfter (afters: list string) (value: T)`:::
|
||||
Indicates that `value` must be placed _after_ each of the attribute names in the given list. For example
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
foo.bar = {
|
||||
a = 0;
|
||||
b = hm.dag.entryAfter [ "a" ] 1;
|
||||
}
|
||||
----
|
||||
+
|
||||
would place `b` after `a` in the graph.
|
||||
+
|
||||
`hm.dag.entryBefore (befores: list string) (value: T)`:::
|
||||
Indicates that `value` must be placed _before_ each of the attribute names in the given list. For example
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
foo.bar = {
|
||||
b = hm.dag.entryBefore [ "a" ] 1;
|
||||
a = 0;
|
||||
}
|
||||
----
|
||||
+
|
||||
would place `b` before `a` in the graph.
|
||||
+
|
||||
`hm.dag.entryBetween (befores: list string) (afters: list string) (value: T)`:::
|
||||
Indicates that `value` must be placed _before_ the attribute names in the first list and _after_ the attribute names in the second list. For example
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
foo.bar = {
|
||||
a = 0;
|
||||
c = hm.dag.entryBetween [ "b" ] [ "a" ] 2;
|
||||
b = 1;
|
||||
}
|
||||
----
|
||||
+
|
||||
would place `c` before `b` and after `a` in the graph.
|
||||
|
||||
`hm.types.gvariant`::
|
||||
This type is useful for options representing {gvariant-description}[GVariant] values. The type accepts all primitive GVariant types as well as arrays and tuples. Dictionaries are not currently supported.
|
||||
+
|
||||
To create a GVariant value you can use a number of provided functions. Examples assume an option `foo.bar` of type `hm.types.gvariant`.
|
||||
+
|
||||
`hm.gvariant.mkBoolean (v: bool)`:::
|
||||
Takes a Nix value `v` to a GVariant `boolean` value. Note, Nix booleans are automatically coerced using this function. That is,
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
foo.bar = hm.gvariant.mkBoolean true;
|
||||
----
|
||||
+
|
||||
is equivalent to
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
foo.bar = true;
|
||||
----
|
||||
`hm.gvariant.mkString (v: string)`:::
|
||||
Takes a Nix value `v` to a GVariant `string` value. Note, Nix strings are automatically coerced using this function. That is,
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
foo.bar = hm.gvariant.mkString "a string";
|
||||
----
|
||||
+
|
||||
is equivalent to
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
foo.bar = "a string";
|
||||
----
|
||||
`hm.gvariant.mkObjectpath (v: string)`:::
|
||||
Takes a Nix value `v` to a GVariant `objectpath` value.
|
||||
`hm.gvariant.mkUchar (v: string)`:::
|
||||
Takes a Nix value `v` to a GVariant `uchar` value.
|
||||
`hm.gvariant.mkInt16 (v: int)`:::
|
||||
Takes a Nix value `v` to a GVariant `int16` value.
|
||||
`hm.gvariant.mkUint16 (v: int)`:::
|
||||
Takes a Nix value `v` to a GVariant `uint16` value.
|
||||
`hm.gvariant.mkInt32 (v: int)`:::
|
||||
Takes a Nix value `v` to a GVariant `int32` value. Note, Nix integers are automatically coerced using this function. That is,
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
foo.bar = hm.gvariant.mkInt32 7;
|
||||
----
|
||||
+
|
||||
is equivalent to
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
foo.bar = 7;
|
||||
----
|
||||
`hm.gvariant.mkUint32 (v: int)`:::
|
||||
Takes a Nix value `v` to a GVariant `uint32` value.
|
||||
`hm.gvariant.mkInt64 (v: int)`:::
|
||||
Takes a Nix value `v` to a GVariant `int64` value.
|
||||
`hm.gvariant.mkUint64 (v: int)`:::
|
||||
Takes a Nix value `v` to a GVariant `uint64` value.
|
||||
`hm.gvariant.mkDouble (v: double)`:::
|
||||
Takes a Nix value `v` to a GVariant `double` value. Note, Nix floats are automatically coerced using this function. That is,
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
foo.bar = hm.gvariant.mkDouble 3.14;
|
||||
----
|
||||
+
|
||||
is equivalent to
|
||||
+
|
||||
[source,nix]
|
||||
----
|
||||
foo.bar = 3.14;
|
||||
----
|
||||
+
|
||||
`hm.gvariant.mkArray type elements`:::
|
||||
Builds a GVariant array containing the given list of elements, where each element is a GVariant value of the given type. The `type` value can be constructed using
|
||||
+
|
||||
--
|
||||
- `hm.gvariant.type.string`
|
||||
- `hm.gvariant.type.boolean`
|
||||
- `hm.gvariant.type.uchar`
|
||||
- `hm.gvariant.type.int16`
|
||||
- `hm.gvariant.type.uint16`
|
||||
- `hm.gvariant.type.int32`
|
||||
- `hm.gvariant.type.uint32`
|
||||
- `hm.gvariant.type.int64`
|
||||
- `hm.gvariant.type.uint64`
|
||||
- `hm.gvariant.type.double`
|
||||
- `hm.gvariant.type.arrayOf type`
|
||||
- `hm.gvariant.type.maybeOf type`
|
||||
- `hm.gvariant.type.tupleOf types`
|
||||
--
|
||||
+
|
||||
where `type` and `types` are themselves a type and list of types, respectively.
|
||||
+
|
||||
`hm.gvariant.mkEmptyArray type`:::
|
||||
An alias of `hm.gvariant.mkArray type []`.
|
||||
+
|
||||
`hm.gvariant.mkNothing type`:::
|
||||
Builds a GVariant maybe value whose (non-existent) element is of the given type. The `type` value is constructed as described for the `mkArray` function above.
|
||||
+
|
||||
`hm.gvariant.mkJust element`:::
|
||||
Builds a GVariant maybe value containing the given GVariant element.
|
||||
+
|
||||
`hm.gvariant.mkTuple elements`:::
|
||||
Builds a GVariant tuple containing the given list of elements, where each element is a GVariant value.
|
||||
26
flake.nix
Normal file
26
flake.nix
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
description = "Home Manager for Nix";
|
||||
|
||||
outputs = { self, nixpkgs }: rec {
|
||||
nixosModules.home-manager = import ./nixos;
|
||||
nixosModule = self.nixosModules.home-manager;
|
||||
|
||||
darwinModules.home-manager = import ./nix-darwin;
|
||||
darwinModule = self.darwinModules.home-manager;
|
||||
|
||||
lib = {
|
||||
hm = import ./modules/lib { lib = nixpkgs.lib; };
|
||||
homeManagerConfiguration = { configuration, system, homeDirectory
|
||||
, username, extraSpecialArgs ? { }
|
||||
, pkgs ? builtins.getAttr system nixpkgs.outputs.legacyPackages
|
||||
, check ? true }@args:
|
||||
import ./modules {
|
||||
inherit pkgs check extraSpecialArgs;
|
||||
configuration = { ... }: {
|
||||
imports = [ configuration ];
|
||||
home = { inherit homeDirectory username; };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
56
format
Executable file
56
format
Executable file
@@ -0,0 +1,56 @@
|
||||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/05f0934825c2a0750d4888c4735f9420c906b388.tar.gz -i bash -p findutils nixfmt
|
||||
|
||||
CHECK_ARG=
|
||||
|
||||
case $1 in
|
||||
-h)
|
||||
echo "$0 [-c]"
|
||||
;;
|
||||
-c)
|
||||
CHECK_ARG=-c
|
||||
;;
|
||||
esac
|
||||
|
||||
# The first block of excludes are files where nixfmt does a poor job,
|
||||
# IMHO. The second block of excludes are files touched by open pull
|
||||
# requests and we want to avoid merge conflicts.
|
||||
find . -name '*.nix' \
|
||||
! -path ./modules/programs/irssi.nix \
|
||||
\
|
||||
! -path ./home-manager/home-manager.nix \
|
||||
! -path ./modules/default.nix \
|
||||
! -path ./modules/files.nix \
|
||||
! -path ./modules/home-environment.nix \
|
||||
! -path ./modules/lib/default.nix \
|
||||
! -path ./modules/lib/file-type.nix \
|
||||
! -path ./modules/manual.nix \
|
||||
! -path ./modules/misc/news.nix \
|
||||
! -path ./modules/misc/nixpkgs.nix \
|
||||
! -path ./modules/misc/xdg.nix \
|
||||
! -path ./modules/modules.nix \
|
||||
! -path ./modules/programs/afew.nix \
|
||||
! -path ./modules/programs/bash.nix \
|
||||
! -path ./modules/programs/firefox.nix \
|
||||
! -path ./modules/programs/gpg.nix \
|
||||
! -path ./modules/programs/lesspipe.nix \
|
||||
! -path ./modules/programs/ssh.nix \
|
||||
! -path ./modules/programs/tmux.nix \
|
||||
! -path ./modules/programs/zsh.nix \
|
||||
! -path ./modules/services/gpg-agent.nix \
|
||||
! -path ./modules/services/kbfs.nix \
|
||||
! -path ./modules/services/keybase.nix \
|
||||
! -path ./modules/services/mpd.nix \
|
||||
! -path ./modules/services/sxhkd.nix \
|
||||
! -path ./modules/services/window-managers/i3.nix \
|
||||
! -path ./modules/systemd.nix \
|
||||
! -path ./nix-darwin/default.nix \
|
||||
! -path ./tests/default.nix \
|
||||
! -path ./tests/modules/home-environment/default.nix \
|
||||
! -path ./tests/modules/home-environment/session-variables.nix \
|
||||
! -path ./tests/modules/programs/gpg/override-defaults.nix \
|
||||
! -path ./tests/modules/programs/zsh/session-variables.nix \
|
||||
! -path ./tests/modules/services/sxhkd/service.nix \
|
||||
! -path ./tests/modules/systemd/services.nix \
|
||||
! -path ./tests/modules/systemd/session-variables.nix \
|
||||
-exec nixfmt $CHECK_ARG {} +
|
||||
357
home-manager/completion.bash
Normal file
357
home-manager/completion.bash
Normal file
@@ -0,0 +1,357 @@
|
||||
#!/bin/env bash
|
||||
|
||||
##################################################
|
||||
|
||||
# « home-manager » command-line completion
|
||||
#
|
||||
# © 2019 "Sam Boosalis" <samboosalis@gmail.com>
|
||||
#
|
||||
# MIT License
|
||||
#
|
||||
|
||||
##################################################
|
||||
# Contributing:
|
||||
|
||||
# Compatibility — Bash 3.
|
||||
#
|
||||
# OSX won't update Bash 3 (last updated circa 2009) to Bash 4,
|
||||
# and we'd like this completion script to work on both Linux and Mac.
|
||||
#
|
||||
# For example, OSX Yosemite (released circa 2014) ships with Bash 3:
|
||||
#
|
||||
# $ echo $BASH_VERSION
|
||||
# 3.2
|
||||
#
|
||||
# While Ubuntu LTS 14.04 (a.k.a. Trusty, also released circa 2016)
|
||||
# ships with the latest version, Bash 4 (updated circa 2016):
|
||||
#
|
||||
# $ echo $BASH_VERSION
|
||||
# 4.3
|
||||
#
|
||||
|
||||
# Testing
|
||||
#
|
||||
# (1) Invoke « shellcheck »
|
||||
#
|
||||
# * source: « https://github.com/koalaman/shellcheck »
|
||||
# * run: « shellcheck ./share/bash-completion/completions/home-manager »
|
||||
#
|
||||
# (2) Interpret via Bash 3
|
||||
#
|
||||
# * run: « bash --noprofile --norc ./share/bash-completion/completions/home-manager »
|
||||
#
|
||||
|
||||
##################################################
|
||||
# Examples:
|
||||
|
||||
# $ home-manager <TAB>
|
||||
#
|
||||
# -A
|
||||
# -I
|
||||
# -f
|
||||
# --file
|
||||
# -h
|
||||
# --help
|
||||
# -n
|
||||
# --dry-run
|
||||
# -v
|
||||
# --verbose
|
||||
# build
|
||||
# edit
|
||||
# expire-generations
|
||||
# generations
|
||||
# help
|
||||
# news
|
||||
# packages
|
||||
# remove-generations
|
||||
# switch
|
||||
# uninstall
|
||||
|
||||
# $ home-manager e<TAB>
|
||||
#
|
||||
# edit
|
||||
# expire-generations
|
||||
|
||||
# $ home-manager remove-generations 20<TAB>
|
||||
#
|
||||
# 200
|
||||
# 201
|
||||
# 202
|
||||
# 203
|
||||
|
||||
##################################################
|
||||
# Notes:
|
||||
|
||||
# « home-manager » Subcommands:
|
||||
#
|
||||
# help
|
||||
# edit
|
||||
# build
|
||||
# switch
|
||||
# generations
|
||||
# remove-generations
|
||||
# expire-generations
|
||||
# packages
|
||||
# news
|
||||
# uninstall
|
||||
|
||||
# « home-manager » Options:
|
||||
#
|
||||
# -b EXT
|
||||
# -f FILE
|
||||
# --file FILE
|
||||
# -A ATTRIBUTE
|
||||
# -I PATH
|
||||
# -v
|
||||
# --verbose
|
||||
# -n
|
||||
# --dry-run
|
||||
# -h
|
||||
# --help
|
||||
|
||||
# $ home-manager
|
||||
#
|
||||
# Usage: /home/sboo/.nix-profile/bin/home-manager [OPTION] COMMAND
|
||||
#
|
||||
# Options
|
||||
#
|
||||
# -f FILE The home configuration file.
|
||||
# Default is '~/.config/nixpkgs/home.nix'.
|
||||
# -A ATTRIBUTE Optional attribute that selects a configuration
|
||||
# expression in the configuration file.
|
||||
# -I PATH Add a path to the Nix expression search path.
|
||||
# -b EXT Move existing files to new path rather than fail.
|
||||
# -v Verbose output
|
||||
# -n Do a dry run, only prints what actions would be taken
|
||||
# -h Print this help
|
||||
#
|
||||
# Commands
|
||||
#
|
||||
# help Print this help
|
||||
#
|
||||
# edit Open the home configuration in $EDITOR
|
||||
#
|
||||
# build Build configuration into result directory
|
||||
#
|
||||
# switch Build and activate configuration
|
||||
#
|
||||
# generations List all home environment generations
|
||||
#
|
||||
# remove-generations ID...
|
||||
# Remove indicated generations. Use 'generations' command to
|
||||
# find suitable generation numbers.
|
||||
#
|
||||
# expire-generations TIMESTAMP
|
||||
# Remove generations older than TIMESTAMP where TIMESTAMP is
|
||||
# interpreted as in the -d argument of the date tool. For
|
||||
# example "-30 days" or "2018-01-01".
|
||||
#
|
||||
# packages List all packages installed in home-manager-path
|
||||
#
|
||||
# news Show news entries in a pager
|
||||
#
|
||||
# uninstall Remove Home Manager
|
||||
#
|
||||
##################################################
|
||||
# Dependencies:
|
||||
|
||||
command -v home-manager >/dev/null
|
||||
command -v grep >/dev/null
|
||||
command -v sed >/dev/null
|
||||
|
||||
##################################################
|
||||
# Code:
|
||||
|
||||
_home-manager_list-generation-identifiers ()
|
||||
|
||||
{
|
||||
|
||||
home-manager generations | sed -n -e 's/^................ : id \([[:alnum:]]\+\) -> .*/\1/p'
|
||||
|
||||
}
|
||||
|
||||
# NOTES
|
||||
#
|
||||
# (1) the « sed -n -e 's/.../.../p' » invocation:
|
||||
#
|
||||
# * the « -e '...' » option takes a Sed Script.
|
||||
# * the « -n » option only prints when « .../p » would print.
|
||||
# * the « s/xxx/yyy/ » Sed Script substitutes « yyy » whenever « xxx » is matched.
|
||||
#
|
||||
# (2) the « '^................ : id \([[:alnum:]]\+\) -> .*' » regular expression:
|
||||
#
|
||||
# * matches « 199 », for example, in the line « 2019-03-13 15:26 : id 199 -> /nix/store/mv619y9pzgsx3kndq0q7fjfvbqqdy5k8-home-manager-generation »
|
||||
#
|
||||
#
|
||||
|
||||
#------------------------------------------------#
|
||||
|
||||
# shellcheck disable=SC2120
|
||||
_home-manager_list-nix-attributes ()
|
||||
|
||||
{
|
||||
local HomeFile
|
||||
local HomeAttrsString
|
||||
# local HomeAttrsArray
|
||||
# local HomeAttr
|
||||
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
HomeFile=$(readlink -f "$(_home-manager_get-default-home-file)")
|
||||
else
|
||||
HomeFile="$1"
|
||||
fi
|
||||
|
||||
HomeAttrsString=$(nix-instantiate --eval -E "let home = import ${HomeFile}; in (builtins.trace (builtins.toString (builtins.attrNames home)) null)" |& grep '^trace: ')
|
||||
HomeAttrsString="${HomeAttrsString#trace: }"
|
||||
|
||||
echo "${HomeAttrsString}"
|
||||
|
||||
# IFS=" " read -ar HomeAttrsArray <<< "${HomeAttrsString}"
|
||||
#
|
||||
# local HomeAttr
|
||||
# for HomeAttr in "${HomeAttrsArray[@]}"
|
||||
# do
|
||||
# echo "${HomeAttr}"
|
||||
# done
|
||||
|
||||
}
|
||||
|
||||
# e.g.:
|
||||
#
|
||||
# $ nix-instantiate --eval -E 'let home = import /home/sboo/configuration/configs/nixpkgs/home-attrs.nix; in (builtins.trace (builtins.toString (builtins.attrNames home)) null)' 1>/dev/null
|
||||
# trace: darwin linux
|
||||
#
|
||||
# $ _home-manager_list-nix-attributes
|
||||
# linux darwin
|
||||
#
|
||||
|
||||
#------------------------------------------------#
|
||||
|
||||
_home-manager_get-default-home-file ()
|
||||
|
||||
{
|
||||
local HomeFileDefault
|
||||
|
||||
HomeFileDefault="$(_home-manager_xdg-get-config-home)/nixpkgs/home.nix"
|
||||
|
||||
echo "${HomeFileDefault}"
|
||||
}
|
||||
|
||||
# e.g.:
|
||||
#
|
||||
# $ _home-manager_get-default-home-file
|
||||
# ~/.config/nixpkgs/home.nix
|
||||
#
|
||||
|
||||
##################################################
|
||||
# XDG-BaseDirs:
|
||||
|
||||
_home-manager_xdg-get-config-home () {
|
||||
|
||||
echo "${XDG_CONFIG_HOME:-$HOME/.config}"
|
||||
|
||||
}
|
||||
|
||||
#------------------------------------------------#
|
||||
|
||||
_home-manager_xdg-get-data-home () {
|
||||
|
||||
echo "${XDG_DATA_HOME:-$HOME/.local/share}"
|
||||
|
||||
}
|
||||
|
||||
|
||||
#------------------------------------------------#
|
||||
_home-manager_xdg-get-cache-home () {
|
||||
|
||||
echo "${XDG_CACHE_HOME:-$HOME/.cache}"
|
||||
|
||||
}
|
||||
|
||||
##################################################
|
||||
|
||||
# shellcheck disable=SC2207
|
||||
_home-manager_completions ()
|
||||
{
|
||||
|
||||
#--------------------------#
|
||||
|
||||
local Subcommands
|
||||
Subcommands=( "help" "edit" "build" "instantiate" "switch" "generations" "remove-generations" "expire-generations" "packages" "news" "uninstall" )
|
||||
|
||||
# ^ « home-manager »'s subcommands.
|
||||
|
||||
#--------------------------#
|
||||
|
||||
local Options
|
||||
Options=( "-f" "--file" "-b" "-A" "-I" "-h" "--help" "-n" "--dry-run" "-v" "--verbose" "--show-trace" \
|
||||
"-j" "--max-jobs" )
|
||||
|
||||
# ^ « home-manager »'s options.
|
||||
|
||||
#--------------------------#
|
||||
|
||||
local CurrentWord
|
||||
CurrentWord="${COMP_WORDS[$COMP_CWORD]}"
|
||||
|
||||
# ^ the word currently being completed
|
||||
|
||||
local PreviousWord
|
||||
if [ "$COMP_CWORD" -ge 1 ]
|
||||
then
|
||||
PreviousWord="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
else
|
||||
PreviousWord=""
|
||||
fi
|
||||
|
||||
# ^ the word to the left of the current word.
|
||||
#
|
||||
# e.g. in « home-manager -v -f ./<TAB> »:
|
||||
#
|
||||
# PreviousWord="-f"
|
||||
# CurrentWord="./"
|
||||
|
||||
#--------------------------#
|
||||
|
||||
COMPREPLY=()
|
||||
|
||||
case "$PreviousWord" in
|
||||
|
||||
"-f"|"--file")
|
||||
|
||||
COMPREPLY+=( $( compgen -A file -- "$CurrentWord") )
|
||||
;;
|
||||
|
||||
"-I")
|
||||
|
||||
COMPREPLY+=( $( compgen -A directory -- "$CurrentWord") )
|
||||
;;
|
||||
|
||||
"-A")
|
||||
|
||||
# shellcheck disable=SC2119
|
||||
COMPREPLY+=( $( compgen -W "$(_home-manager_list-nix-attributes)" -- "$CurrentWord") )
|
||||
;;
|
||||
|
||||
"remove-generations")
|
||||
|
||||
COMPREPLY+=( $( compgen -W "$(_home-manager_list-generation-identifiers)" -- "$CurrentWord" ) )
|
||||
;;
|
||||
|
||||
*)
|
||||
|
||||
COMPREPLY+=( $( compgen -W "${Subcommands[*]}" -- "$CurrentWord" ) )
|
||||
COMPREPLY+=( $( compgen -W "${Options[*]}" -- "$CurrentWord" ) )
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
#--------------------------#
|
||||
}
|
||||
|
||||
##################################################
|
||||
|
||||
complete -F _home-manager_completions -o default home-manager
|
||||
|
||||
#complete -W "help edit build switch generations remove-generations expire-generations packages news" home-manager
|
||||
54
home-manager/completion.zsh
Normal file
54
home-manager/completion.zsh
Normal file
@@ -0,0 +1,54 @@
|
||||
#compdef home-manager
|
||||
|
||||
local state ret=1
|
||||
|
||||
_arguments \
|
||||
'-A[attribute]:ATTRIBUTE:()' \
|
||||
'-I[search path]:PATH:_files -/' \
|
||||
'-b[backup files]:EXT:()' \
|
||||
'--cores[cores]:NUM:()' \
|
||||
'--keep-failed[keep failed]' \
|
||||
'--keep-going[keep going]' \
|
||||
'(-h --help)'{--help,-h}'[help]' \
|
||||
'(-v --verbose)'{--verbose,-v}'[verbose]' \
|
||||
'(-n --dry-run)'{--dry-run,-n}'[dry run]' \
|
||||
'(-f --file)'{--file,-f}'[configuration file]:FILE:_files' \
|
||||
'(-j --max-jobs)'{--max-jobs,-j}'[max jobs]:NUM:()' \
|
||||
'--option[option]:NAME VALUE:()' \
|
||||
'--show-trace[show trace]' \
|
||||
'1: :->cmds' \
|
||||
'*:: :->args' && ret=0
|
||||
|
||||
case "$state" in
|
||||
cmds)
|
||||
_values 'command' \
|
||||
'help[help]' \
|
||||
'edit[edit]' \
|
||||
'build[build]' \
|
||||
'switch[switch]' \
|
||||
'generations[list generations]' \
|
||||
'remove-generations[remove generations]' \
|
||||
'expire-generations[expire generations]' \
|
||||
'packages[managed packages]' \
|
||||
'news[read the news]' \
|
||||
'uninstall[uninstall]' && ret=0
|
||||
;;
|
||||
args)
|
||||
case $line[1] in
|
||||
remove-generations)
|
||||
_values 'generations' \
|
||||
$(home-manager generations | cut -d ' ' -f 5) && ret=0
|
||||
;;
|
||||
build|switch)
|
||||
_arguments \
|
||||
'--cores[cores]:NUM:()' \
|
||||
'--keep-failed[keep failed]' \
|
||||
'--keep-going[keep going]' \
|
||||
'--max-jobs[max jobs]:NUM:()' \
|
||||
'--option[option]:NAME VALUE:()' \
|
||||
'--show-trace[show trace]'
|
||||
;;
|
||||
esac
|
||||
esac
|
||||
|
||||
return ret
|
||||
@@ -1,41 +1,36 @@
|
||||
{ pkgs, modulesPath ? "$HOME/.config/nixpkgs/home-manager/modules" }:
|
||||
{ runCommand, lib, bash, coreutils, findutils, gnused, less
|
||||
|
||||
# Extra path to Home Manager. If set then this path will be tried
|
||||
# before `$HOME/.config/nixpkgs/home-manager` and
|
||||
# `$HOME/.nixpkgs/home-manager`.
|
||||
, path ? null }:
|
||||
|
||||
let
|
||||
|
||||
homeManagerExpr = pkgs.writeText "home-manager.nix" ''
|
||||
{ pkgs ? import <nixpkgs> {}, confPath }:
|
||||
pathStr = if path == null then "" else path;
|
||||
|
||||
let
|
||||
env = import <home-manager> {
|
||||
configuration = import confPath;
|
||||
pkgs = pkgs;
|
||||
};
|
||||
in
|
||||
{
|
||||
inherit (env) activation-script;
|
||||
}
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
pkgs.stdenv.mkDerivation {
|
||||
name = "home-manager";
|
||||
|
||||
phases = [ "installPhase" ];
|
||||
|
||||
installPhase = ''
|
||||
install -v -D -m755 ${./home-manager} $out/bin/home-manager
|
||||
|
||||
substituteInPlace $out/bin/home-manager \
|
||||
--subst-var-by bash "${pkgs.bash}" \
|
||||
--subst-var-by coreutils "${pkgs.coreutils}" \
|
||||
--subst-var-by MODULES_PATH '${modulesPath}' \
|
||||
--subst-var-by HOME_MANAGER_EXPR_PATH "${homeManagerExpr}"
|
||||
'';
|
||||
|
||||
meta = with pkgs.stdenv.lib; {
|
||||
in runCommand "home-manager" {
|
||||
preferLocalBuild = true;
|
||||
allowSubstitutes = false;
|
||||
meta = with lib; {
|
||||
description = "A user environment configurator";
|
||||
maintainers = [ maintainers.rycee ];
|
||||
platforms = platforms.linux;
|
||||
platforms = platforms.unix;
|
||||
license = licenses.mit;
|
||||
};
|
||||
}
|
||||
} ''
|
||||
install -v -D -m755 ${./home-manager} $out/bin/home-manager
|
||||
|
||||
substituteInPlace $out/bin/home-manager \
|
||||
--subst-var-by bash "${bash}" \
|
||||
--subst-var-by coreutils "${coreutils}" \
|
||||
--subst-var-by findutils "${findutils}" \
|
||||
--subst-var-by gnused "${gnused}" \
|
||||
--subst-var-by less "${less}" \
|
||||
--subst-var-by HOME_MANAGER_PATH '${pathStr}'
|
||||
|
||||
install -D -m755 ${./completion.bash} \
|
||||
$out/share/bash-completion/completions/home-manager
|
||||
install -D -m755 ${./completion.zsh} \
|
||||
$out/share/zsh/site-functions/_home-manager
|
||||
''
|
||||
|
||||
@@ -1,12 +1,37 @@
|
||||
#!@bash@/bin/bash
|
||||
|
||||
# This code explicitly requires GNU Core Utilities and we therefore
|
||||
# need to ensure they are prioritized over any other similarly named
|
||||
# tools on the system.
|
||||
PATH=@coreutils@/bin:$PATH
|
||||
# Prepare to use tools from Nixpkgs.
|
||||
PATH=@coreutils@/bin:@findutils@/bin:@gnused@/bin:@less@/bin${PATH:+:}$PATH
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
function errorEcho() {
|
||||
# shellcheck disable=2048,2086
|
||||
echo $* >&2
|
||||
}
|
||||
|
||||
function setVerboseAndDryRun() {
|
||||
if [[ -v VERBOSE ]]; then
|
||||
export VERBOSE_ARG="--verbose"
|
||||
else
|
||||
export VERBOSE_ARG=""
|
||||
fi
|
||||
|
||||
if [[ -v DRY_RUN ]] ; then
|
||||
export DRY_RUN_CMD=echo
|
||||
else
|
||||
export DRY_RUN_CMD=""
|
||||
fi
|
||||
}
|
||||
|
||||
function setWorkDir() {
|
||||
if [[ ! -v WORK_DIR ]]; then
|
||||
WORK_DIR="$(mktemp --tmpdir -d home-manager-build.XXXXXXXXXX)"
|
||||
# shellcheck disable=2064
|
||||
trap "rm -r '$WORK_DIR'" EXIT
|
||||
fi
|
||||
}
|
||||
|
||||
# Attempts to set the HOME_MANAGER_CONFIG global variable.
|
||||
#
|
||||
# If no configuration file can be found then this function will print
|
||||
@@ -14,7 +39,7 @@ set -euo pipefail
|
||||
function setConfigFile() {
|
||||
if [[ -v HOME_MANAGER_CONFIG ]] ; then
|
||||
if [[ ! -e "$HOME_MANAGER_CONFIG" ]] ; then
|
||||
echo "No configure file found at $HOME_MANAGER_CONFIG"
|
||||
errorEcho "No configuration file found at $HOME_MANAGER_CONFIG"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -22,155 +47,571 @@ function setConfigFile() {
|
||||
return
|
||||
fi
|
||||
|
||||
local defaultConfFile="${XDG_CONFIG_HOME:-$HOME/.config}/nixpkgs/home.nix"
|
||||
local confFile
|
||||
for confFile in "$HOME/.config/nixpkgs/home.nix" \
|
||||
for confFile in "$defaultConfFile" \
|
||||
"$HOME/.nixpkgs/home.nix" ; do
|
||||
if [[ -e "$confFile" ]] ; then
|
||||
HOME_MANAGER_CONFIG="$confFile"
|
||||
HOME_MANAGER_CONFIG="$(realpath "$confFile")"
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
||||
echo "No configuration file found. " \
|
||||
"Please create one at ~/.config/nixpkgs/home.nix"
|
||||
errorEcho "No configuration file found." \
|
||||
"Please create one at $defaultConfFile"
|
||||
exit 1
|
||||
}
|
||||
|
||||
function setHomeManagerModulesPath() {
|
||||
local modulesPath
|
||||
for modulesPath in "@MODULES_PATH@" \
|
||||
"$HOME/.nixpkgs/home-manager/modules" ; do
|
||||
if [[ -e "$modulesPath" ]] ; then
|
||||
export NIX_PATH="$NIX_PATH${NIX_PATH:+:}home-manager=$modulesPath"
|
||||
function setHomeManagerNixPath() {
|
||||
local path
|
||||
for path in "@HOME_MANAGER_PATH@" \
|
||||
"${XDG_CONFIG_HOME:-$HOME/.config}/nixpkgs/home-manager" \
|
||||
"$HOME/.nixpkgs/home-manager" ; do
|
||||
if [[ -e "$path" || "$path" =~ ^https?:// ]] ; then
|
||||
export NIX_PATH="home-manager=$path${NIX_PATH:+:}$NIX_PATH"
|
||||
return
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
function doBuild() {
|
||||
if [[ -z "$1" ]]; then
|
||||
echo "Need to provide generation output path."
|
||||
exit 1
|
||||
function setFlakeAttribute() {
|
||||
local configFlake="${XDG_CONFIG_HOME:-$HOME/.config}/nixpkgs/flake.nix"
|
||||
if [[ -z $FLAKE_ARG && ! -v HOME_MANAGER_CONFIG && -e "$configFlake" ]]; then
|
||||
FLAKE_ARG="$(dirname "$(readlink -f "$configFlake")")"
|
||||
fi
|
||||
|
||||
if [[ -e "$1" ]]; then
|
||||
echo "The output path $1 already exists."
|
||||
if [[ -n "$FLAKE_ARG" ]]; then
|
||||
local flake="${FLAKE_ARG%#*}"
|
||||
case $FLAKE_ARG in
|
||||
*#*)
|
||||
local name="${FLAKE_ARG#*#}"
|
||||
;;
|
||||
*)
|
||||
local name="$USER@$(hostname)"
|
||||
if [ "$(nix eval "$flake#homeConfigurations" --apply "x: x ? \"$name\"")" = "false" ]; then
|
||||
name="$USER"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
export FLAKE_CONFIG_URI="$flake#homeConfigurations.\"$name\""
|
||||
fi
|
||||
}
|
||||
|
||||
function doInstantiate() {
|
||||
setFlakeAttribute
|
||||
if [[ -v FLAKE_CONFIG_URI ]]; then
|
||||
errorEcho "Can't instantiate a flake configuration"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
setConfigFile
|
||||
setHomeManagerModulesPath
|
||||
setHomeManagerNixPath
|
||||
|
||||
output="$(realpath "$1")"
|
||||
|
||||
if [[ $? -ne 0 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export NIX_PATH="$NIX_PATH${NIX_PATH:+:}home-manager=@MODULES_PATH@"
|
||||
|
||||
local extraArgs
|
||||
extraArgs=""
|
||||
local extraArgs=()
|
||||
|
||||
for p in "${EXTRA_NIX_PATH[@]}"; do
|
||||
extraArgs="$extraArgs -I $p"
|
||||
extraArgs=("${extraArgs[@]}" "-I" "$p")
|
||||
done
|
||||
|
||||
if [[ -v VERBOSE ]]; then
|
||||
extraArgs="$extraArgs --show-trace"
|
||||
extraArgs=("${extraArgs[@]}" "--show-trace")
|
||||
fi
|
||||
|
||||
nix-build $extraArgs \
|
||||
"@HOME_MANAGER_EXPR_PATH@" \
|
||||
--argstr confPath "$HOME_MANAGER_CONFIG" \
|
||||
-A activation-script \
|
||||
-o "$output"
|
||||
nix-instantiate \
|
||||
"<home-manager/home-manager/home-manager.nix>" \
|
||||
"${extraArgs[@]}" \
|
||||
"${PASSTHROUGH_OPTS[@]}" \
|
||||
--argstr confPath "$HOME_MANAGER_CONFIG" \
|
||||
--argstr confAttr "$HOME_MANAGER_CONFIG_ATTRIBUTE"
|
||||
}
|
||||
|
||||
function doBuildAttr() {
|
||||
setConfigFile
|
||||
setHomeManagerNixPath
|
||||
|
||||
local extraArgs=("$@")
|
||||
|
||||
for p in "${EXTRA_NIX_PATH[@]}"; do
|
||||
extraArgs=("${extraArgs[@]}" "-I" "$p")
|
||||
done
|
||||
|
||||
if [[ -v VERBOSE ]]; then
|
||||
extraArgs=("${extraArgs[@]}" "--show-trace")
|
||||
fi
|
||||
|
||||
nix-build \
|
||||
"<home-manager/home-manager/home-manager.nix>" \
|
||||
"${extraArgs[@]}" \
|
||||
"${PASSTHROUGH_OPTS[@]}" \
|
||||
--argstr confPath "$HOME_MANAGER_CONFIG" \
|
||||
--argstr confAttr "$HOME_MANAGER_CONFIG_ATTRIBUTE"
|
||||
}
|
||||
|
||||
# Presents news to the user. Takes as argument the path to a "news
|
||||
# info" file as generated by `buildNews`.
|
||||
function presentNews() {
|
||||
local infoFile="$1"
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
. "$infoFile"
|
||||
|
||||
# shellcheck disable=2154
|
||||
if [[ $newsNumUnread -eq 0 ]]; then
|
||||
return
|
||||
elif [[ "$newsDisplay" == "silent" ]]; then
|
||||
return
|
||||
elif [[ "$newsDisplay" == "notify" ]]; then
|
||||
local msg
|
||||
if [[ $newsNumUnread -eq 1 ]]; then
|
||||
msg="There is an unread and relevant news item.\n"
|
||||
msg+="Read it by running the command '$(basename "$0") news'."
|
||||
else
|
||||
msg="There are $newsNumUnread unread and relevant news items.\n"
|
||||
msg+="Read them by running the command '$(basename "$0") news'."
|
||||
fi
|
||||
|
||||
# Not actually an error but here stdout is reserved for
|
||||
# nix-build output.
|
||||
errorEcho
|
||||
errorEcho -e "$msg"
|
||||
errorEcho
|
||||
|
||||
if [[ -v DISPLAY ]] && type -P notify-send > /dev/null; then
|
||||
notify-send "Home Manager" "$msg"
|
||||
fi
|
||||
elif [[ "$newsDisplay" == "show" ]]; then
|
||||
doShowNews --unread
|
||||
else
|
||||
errorEcho "Unknown 'news.display' setting '$newsDisplay'."
|
||||
fi
|
||||
}
|
||||
|
||||
function doEdit() {
|
||||
if [[ ! -v EDITOR || -z $EDITOR ]]; then
|
||||
errorEcho "Please set the \$EDITOR environment variable"
|
||||
return 1
|
||||
fi
|
||||
|
||||
setConfigFile
|
||||
|
||||
# Don't quote $EDITOR in order to support values including options, e.g.,
|
||||
# "code --wait".
|
||||
#
|
||||
# shellcheck disable=2086
|
||||
exec $EDITOR "$HOME_MANAGER_CONFIG"
|
||||
}
|
||||
|
||||
function doBuild() {
|
||||
if [[ ! -w . ]]; then
|
||||
errorEcho "Cannot run build in read-only directory";
|
||||
return 1
|
||||
fi
|
||||
|
||||
setFlakeAttribute
|
||||
if [[ -v FLAKE_CONFIG_URI ]]; then
|
||||
local exitCode=0
|
||||
nix build \
|
||||
"${PASSTHROUGH_OPTS[@]}" \
|
||||
${DRY_RUN+--dry-run} \
|
||||
"$FLAKE_CONFIG_URI.activationPackage" \
|
||||
|| exitCode=1
|
||||
return $exitCode
|
||||
fi
|
||||
|
||||
setWorkDir
|
||||
|
||||
local newsInfo
|
||||
newsInfo=$(buildNews)
|
||||
|
||||
local exitCode
|
||||
|
||||
doBuildAttr --attr activationPackage \
|
||||
&& exitCode=0 || exitCode=1
|
||||
|
||||
presentNews "$newsInfo"
|
||||
|
||||
return $exitCode
|
||||
}
|
||||
|
||||
function doSwitch() {
|
||||
local wrkdir
|
||||
wrkdir="$(mktemp -d)"
|
||||
|
||||
if doBuild "$wrkdir/generation" ; then
|
||||
"$wrkdir/generation/activate"
|
||||
setFlakeAttribute
|
||||
if [[ -v FLAKE_CONFIG_URI ]]; then
|
||||
local exitCode=0
|
||||
nix run \
|
||||
"${PASSTHROUGH_OPTS[@]}" \
|
||||
"$FLAKE_CONFIG_URI.activationPackage" \
|
||||
|| exitCode=1
|
||||
return $exitCode
|
||||
fi
|
||||
|
||||
rm -r "$wrkdir"
|
||||
setWorkDir
|
||||
|
||||
local newsInfo
|
||||
newsInfo=$(buildNews)
|
||||
|
||||
local generation
|
||||
local exitCode=0
|
||||
|
||||
# Build the generation and run the activate script. Note, we
|
||||
# specify an output link so that it is treated as a GC root. This
|
||||
# prevents an unfortunately timed GC from removing the generation
|
||||
# before activation completes.
|
||||
generation="$WORK_DIR/generation"
|
||||
|
||||
doBuildAttr \
|
||||
--out-link "$generation" \
|
||||
--attr activationPackage \
|
||||
&& "$generation/activate" || exitCode=1
|
||||
|
||||
presentNews "$newsInfo"
|
||||
|
||||
return $exitCode
|
||||
}
|
||||
|
||||
function doListGens() {
|
||||
pushd "/nix/var/nix/profiles/per-user/$USER" > /dev/null
|
||||
ls --color=yes -gG --sort time home-manager-*-link \
|
||||
| cut -d' ' -f 4-
|
||||
# Whether to colorize the generations output.
|
||||
local color="never"
|
||||
if [[ ! -v NO_COLOR && -t 1 ]]; then
|
||||
color="always"
|
||||
fi
|
||||
|
||||
pushd "$NIX_STATE_DIR/profiles/per-user/$USER" > /dev/null
|
||||
# shellcheck disable=2012
|
||||
ls --color=$color -gG --time-style=long-iso --sort time home-manager-*-link \
|
||||
| cut -d' ' -f 4- \
|
||||
| sed -E 's/home-manager-([[:digit:]]*)-link/: id \1/'
|
||||
popd > /dev/null
|
||||
}
|
||||
|
||||
# Removes linked generations. Takes as arguments identifiers of
|
||||
# generations to remove.
|
||||
function doRmGenerations() {
|
||||
setVerboseAndDryRun
|
||||
|
||||
pushd "$NIX_STATE_DIR/profiles/per-user/$USER" > /dev/null
|
||||
|
||||
for generationId in "$@"; do
|
||||
local linkName="home-manager-$generationId-link"
|
||||
|
||||
if [[ ! -e $linkName ]]; then
|
||||
errorEcho "No generation with ID $generationId"
|
||||
elif [[ $linkName == $(readlink home-manager) ]]; then
|
||||
errorEcho "Cannot remove the current generation $generationId"
|
||||
else
|
||||
echo Removing generation $generationId
|
||||
$DRY_RUN_CMD rm $VERBOSE_ARG $linkName
|
||||
fi
|
||||
done
|
||||
|
||||
popd > /dev/null
|
||||
}
|
||||
|
||||
function doRmAllGenerations() {
|
||||
$DRY_RUN_CMD rm $VERBOSE_ARG \
|
||||
"$NIX_STATE_DIR/profiles/per-user/$USER/home-manager"*
|
||||
}
|
||||
|
||||
function doExpireGenerations() {
|
||||
local profileDir="$NIX_STATE_DIR/profiles/per-user/$USER"
|
||||
|
||||
local generations
|
||||
generations="$( \
|
||||
find "$profileDir" -name 'home-manager-*-link' -not -newermt "$1" \
|
||||
| sed 's/^.*-\([0-9]*\)-link$/\1/' \
|
||||
)"
|
||||
|
||||
if [[ -n $generations ]]; then
|
||||
# shellcheck disable=2086
|
||||
doRmGenerations $generations
|
||||
elif [[ -v VERBOSE ]]; then
|
||||
echo "No generations to expire"
|
||||
fi
|
||||
}
|
||||
|
||||
function doListPackages() {
|
||||
local outPath
|
||||
outPath="$(nix-env -q --out-path | grep -o '/.*home-manager-path$')"
|
||||
if [[ -n "$outPath" ]] ; then
|
||||
nix-store -q --references "$outPath" | sed 's/[^-]*-//'
|
||||
else
|
||||
echo "No home-manager packages seem to be installed."
|
||||
errorEcho "No home-manager packages seem to be installed."
|
||||
fi
|
||||
}
|
||||
|
||||
function newsReadIdsFile() {
|
||||
local dataDir="${XDG_DATA_HOME:-$HOME/.local/share}/home-manager"
|
||||
local path="$dataDir/news-read-ids"
|
||||
|
||||
# If the path doesn't exist then we should create it, otherwise
|
||||
# Nix will error out when we attempt to use builtins.readFile.
|
||||
if [[ ! -f "$path" ]]; then
|
||||
mkdir -p "$dataDir"
|
||||
touch "$path"
|
||||
fi
|
||||
|
||||
echo "$path"
|
||||
}
|
||||
|
||||
# Builds news meta information to be sourced into this script.
|
||||
#
|
||||
# Note, we suppress build output to remove unnecessary verbosity. We
|
||||
# put the output in the work directory to avoid the risk of an
|
||||
# unfortunately timed GC removing it.
|
||||
function buildNews() {
|
||||
local output
|
||||
output="$WORK_DIR/news-info.sh"
|
||||
|
||||
doBuildAttr \
|
||||
--out-link "$output" \
|
||||
--no-build-output \
|
||||
--quiet \
|
||||
--arg check false \
|
||||
--argstr newsReadIdsFile "$(newsReadIdsFile)" \
|
||||
--attr newsInfo \
|
||||
> /dev/null
|
||||
|
||||
echo "$output"
|
||||
}
|
||||
|
||||
function doShowNews() {
|
||||
setWorkDir
|
||||
|
||||
local infoFile
|
||||
infoFile=$(buildNews) || return 1
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
. "$infoFile"
|
||||
|
||||
# shellcheck disable=2154
|
||||
case $1 in
|
||||
--all)
|
||||
${PAGER:-less} "$newsFileAll"
|
||||
;;
|
||||
--unread)
|
||||
${PAGER:-less} "$newsFileUnread"
|
||||
;;
|
||||
*)
|
||||
errorEcho "Unknown argument $1"
|
||||
return 1
|
||||
esac
|
||||
|
||||
# shellcheck disable=2154
|
||||
if [[ -s "$newsUnreadIdsFile" ]]; then
|
||||
local newsReadIdsFile
|
||||
newsReadIdsFile="$(newsReadIdsFile)"
|
||||
cat "$newsUnreadIdsFile" >> "$newsReadIdsFile"
|
||||
fi
|
||||
}
|
||||
|
||||
function doUninstall() {
|
||||
setVerboseAndDryRun
|
||||
|
||||
echo "This will remove Home Manager from your system."
|
||||
|
||||
if [[ -v DRY_RUN ]]; then
|
||||
echo "This is a dry run, nothing will actually be uninstalled."
|
||||
fi
|
||||
|
||||
local confirmation
|
||||
read -r -n 1 -p "Really uninstall Home Manager? [y/n] " confirmation
|
||||
echo
|
||||
|
||||
case $confirmation in
|
||||
y|Y)
|
||||
echo "Switching to empty Home Manager configuration..."
|
||||
HOME_MANAGER_CONFIG="$(mktemp --tmpdir home-manager.XXXXXXXXXX)"
|
||||
echo "{ lib, ... }: { home.file = lib.mkForce {}; }" > "$HOME_MANAGER_CONFIG"
|
||||
doSwitch
|
||||
$DRY_RUN_CMD nix-env -e home-manager-path || true
|
||||
rm "$HOME_MANAGER_CONFIG"
|
||||
$DRY_RUN_CMD rm $VERBOSE_ARG -r \
|
||||
"${XDG_DATA_HOME:-$HOME/.local/share}/home-manager"
|
||||
$DRY_RUN_CMD rm $VERBOSE_ARG \
|
||||
"$NIX_STATE_DIR/gcroots/per-user/$USER/current-home"
|
||||
;;
|
||||
*)
|
||||
echo "Yay!"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
local deleteProfiles
|
||||
read -r -n 1 \
|
||||
-p 'Remove all Home Manager generations? [y/n] ' \
|
||||
deleteProfiles
|
||||
echo
|
||||
|
||||
case $deleteProfiles in
|
||||
y|Y)
|
||||
doRmAllGenerations
|
||||
echo "All generations are now eligible for garbage collection."
|
||||
;;
|
||||
*)
|
||||
echo "Leaving generations but they may still be garbage collected."
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "Home Manager is uninstalled but your home.nix is left untouched."
|
||||
}
|
||||
|
||||
function doHelp() {
|
||||
echo "Usage: $0 [OPTION] COMMAND"
|
||||
echo
|
||||
echo "Options"
|
||||
echo
|
||||
echo " -f FILE The home configuration file."
|
||||
echo " Default is '~/.config/nixpkgs/home.nix'."
|
||||
echo " -I PATH Add a path to the Nix expression search path."
|
||||
echo " -v Verbose output"
|
||||
echo " -n Do a dry run, only prints what actions would be taken"
|
||||
echo " -h Print this help"
|
||||
echo " -f FILE The home configuration file."
|
||||
echo " Default is '~/.config/nixpkgs/home.nix'."
|
||||
echo " -A ATTRIBUTE Optional attribute that selects a configuration"
|
||||
echo " expression in the configuration file."
|
||||
echo " -I PATH Add a path to the Nix expression search path."
|
||||
echo " --flake flake-uri Use home-manager configuration at flake-uri"
|
||||
echo " -b EXT Move existing files to new path rather than fail."
|
||||
echo " -v Verbose output"
|
||||
echo " -n Do a dry run, only prints what actions would be taken"
|
||||
echo " -h Print this help"
|
||||
echo
|
||||
echo "Options passed on to nix-build(1)"
|
||||
echo
|
||||
echo " --arg(str) NAME VALUE Override inputs passed to home-manager.nix"
|
||||
echo " --cores NUM"
|
||||
echo " --keep-failed"
|
||||
echo " --keep-going"
|
||||
echo " -j, --max-jobs NUM"
|
||||
echo " --option NAME VALUE"
|
||||
echo " --show-trace"
|
||||
echo " --(no-)substitute"
|
||||
echo
|
||||
echo "Commands"
|
||||
echo
|
||||
echo " help Print this help"
|
||||
echo
|
||||
echo " edit Open the home configuration in \$EDITOR"
|
||||
echo
|
||||
echo " build Build configuration into result directory"
|
||||
echo
|
||||
echo " instantiate Instantiate the configuration and print the resulting derivation"
|
||||
echo
|
||||
echo " switch Build and activate configuration"
|
||||
echo
|
||||
echo " generations List all home environment generations"
|
||||
echo
|
||||
echo " remove-generations ID..."
|
||||
echo " Remove indicated generations. Use 'generations' command to"
|
||||
echo " find suitable generation numbers."
|
||||
echo
|
||||
echo " expire-generations TIMESTAMP"
|
||||
echo " Remove generations older than TIMESTAMP where TIMESTAMP is"
|
||||
echo " interpreted as in the -d argument of the date tool. For"
|
||||
echo " example \"-30 days\" or \"2018-01-01\"."
|
||||
echo
|
||||
echo " packages List all packages installed in home-manager-path"
|
||||
echo
|
||||
echo " news Show news entries in a pager"
|
||||
echo
|
||||
echo " uninstall Remove Home Manager"
|
||||
}
|
||||
|
||||
EXTRA_NIX_PATH=()
|
||||
readonly NIX_STATE_DIR="${NIX_STATE_DIR:-/nix/var/nix}"
|
||||
|
||||
while getopts f:I:vnh opt; do
|
||||
EXTRA_NIX_PATH=()
|
||||
HOME_MANAGER_CONFIG_ATTRIBUTE=""
|
||||
PASSTHROUGH_OPTS=()
|
||||
COMMAND=""
|
||||
COMMAND_ARGS=()
|
||||
FLAKE_ARG=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
opt="$1"
|
||||
shift
|
||||
case $opt in
|
||||
f)
|
||||
HOME_MANAGER_CONFIG="$OPTARG"
|
||||
build|instantiate|edit|expire-generations|generations|help|news|packages|remove-generations|switch|uninstall)
|
||||
COMMAND="$opt"
|
||||
;;
|
||||
I)
|
||||
EXTRA_NIX_PATH+=("$OPTARG")
|
||||
-A)
|
||||
HOME_MANAGER_CONFIG_ATTRIBUTE="$1"
|
||||
shift
|
||||
;;
|
||||
v)
|
||||
export VERBOSE=1
|
||||
-I)
|
||||
EXTRA_NIX_PATH+=("$1")
|
||||
shift
|
||||
;;
|
||||
n)
|
||||
export DRY_RUN=1
|
||||
-b)
|
||||
export HOME_MANAGER_BACKUP_EXT="$1"
|
||||
shift
|
||||
;;
|
||||
h)
|
||||
-f|--file)
|
||||
HOME_MANAGER_CONFIG="$1"
|
||||
shift
|
||||
;;
|
||||
--flake)
|
||||
FLAKE_ARG="$1"
|
||||
shift
|
||||
;;
|
||||
--recreate-lock-file|--no-update-lock-file|--no-write-lock-file|--no-registries|--commit-lock-file)
|
||||
PASSTHROUGH_OPTS+=("$opt")
|
||||
;;
|
||||
--update-input)
|
||||
PASSTHROUGH_OPTS+=("$opt" "$1")
|
||||
shift
|
||||
;;
|
||||
--override-input)
|
||||
PASSTHROUGH_OPTS+=("$opt" "$1" "$2")
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
doHelp
|
||||
exit 0
|
||||
;;
|
||||
-n|--dry-run)
|
||||
export DRY_RUN=1
|
||||
;;
|
||||
--option|--arg|--argstr)
|
||||
PASSTHROUGH_OPTS+=("$opt" "$1" "$2")
|
||||
shift 2
|
||||
;;
|
||||
-j|--max-jobs|--cores)
|
||||
PASSTHROUGH_OPTS+=("$opt" "$1")
|
||||
shift
|
||||
;;
|
||||
--keep-failed|--keep-going|--show-trace\
|
||||
|--substitute|--no-substitute)
|
||||
PASSTHROUGH_OPTS+=("$opt")
|
||||
;;
|
||||
-v|--verbose)
|
||||
export VERBOSE=1
|
||||
;;
|
||||
--version)
|
||||
echo 21.05
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option -$OPTARG" >&2
|
||||
doHelp >&2
|
||||
exit 1
|
||||
case $COMMAND in
|
||||
expire-generations|remove-generations)
|
||||
COMMAND_ARGS+=("$opt")
|
||||
;;
|
||||
*)
|
||||
errorEcho "$0: unknown option '$opt'"
|
||||
errorEcho "Run '$0 --help' for usage help"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Get rid of the options.
|
||||
shift "$((OPTIND-1))"
|
||||
if [[ -z $COMMAND ]]; then
|
||||
doHelp >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cmd="$*"
|
||||
|
||||
case "$cmd" in
|
||||
case $COMMAND in
|
||||
edit)
|
||||
doEdit
|
||||
;;
|
||||
build)
|
||||
doBuild "result"
|
||||
doBuild
|
||||
;;
|
||||
instantiate)
|
||||
doInstantiate
|
||||
;;
|
||||
switch)
|
||||
doSwitch
|
||||
@@ -178,14 +619,31 @@ case "$cmd" in
|
||||
generations)
|
||||
doListGens
|
||||
;;
|
||||
remove-generations)
|
||||
doRmGenerations "${COMMAND_ARGS[@]}"
|
||||
;;
|
||||
expire-generations)
|
||||
if [[ ${#COMMAND_ARGS[@]} != 1 ]]; then
|
||||
errorEcho "expire-generations expects one argument, got ${#COMMAND_ARGS[@]}."
|
||||
exit 1
|
||||
else
|
||||
doExpireGenerations "${COMMAND_ARGS[@]}"
|
||||
fi
|
||||
;;
|
||||
packages)
|
||||
doListPackages
|
||||
;;
|
||||
help|--help)
|
||||
news)
|
||||
doShowNews --all
|
||||
;;
|
||||
uninstall)
|
||||
doUninstall
|
||||
;;
|
||||
help)
|
||||
doHelp
|
||||
;;
|
||||
*)
|
||||
echo "Unknown command: $cmd"
|
||||
errorEcho "Unknown command: $COMMAND"
|
||||
doHelp >&2
|
||||
exit 1
|
||||
;;
|
||||
|
||||
88
home-manager/home-manager.nix
Normal file
88
home-manager/home-manager.nix
Normal file
@@ -0,0 +1,88 @@
|
||||
{ pkgs ? import <nixpkgs> {}
|
||||
, confPath
|
||||
, confAttr ? null
|
||||
, check ? true
|
||||
, newsReadIdsFile ? null
|
||||
}:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
|
||||
env = import ../modules {
|
||||
configuration =
|
||||
if confAttr == "" || confAttr == null
|
||||
then confPath
|
||||
else (import confPath).${confAttr};
|
||||
pkgs = pkgs;
|
||||
check = check;
|
||||
};
|
||||
|
||||
newsReadIds =
|
||||
if newsReadIdsFile == null
|
||||
then {}
|
||||
else
|
||||
let
|
||||
ids = splitString "\n" (fileContents newsReadIdsFile);
|
||||
in
|
||||
builtins.listToAttrs (map (id: { name = id; value = null; }) ids);
|
||||
|
||||
newsIsRead = entry: builtins.hasAttr entry.id newsReadIds;
|
||||
|
||||
newsFiltered =
|
||||
let
|
||||
pred = entry: entry.condition && ! newsIsRead entry;
|
||||
in
|
||||
filter pred env.newsEntries;
|
||||
|
||||
newsNumUnread = length newsFiltered;
|
||||
|
||||
newsFileUnread = pkgs.writeText "news-unread.txt" (
|
||||
concatMapStringsSep "\n\n" (entry:
|
||||
let
|
||||
time = replaceStrings ["T"] [" "] (removeSuffix "+00:00" entry.time);
|
||||
in
|
||||
''
|
||||
* ${time}
|
||||
|
||||
${replaceStrings ["\n"] ["\n "] entry.message}
|
||||
''
|
||||
) newsFiltered
|
||||
);
|
||||
|
||||
newsFileAll = pkgs.writeText "news-all.txt" (
|
||||
concatMapStringsSep "\n\n" (entry:
|
||||
let
|
||||
flag = if newsIsRead entry then "read" else "unread";
|
||||
time = replaceStrings ["T"] [" "] (removeSuffix "+00:00" entry.time);
|
||||
in
|
||||
''
|
||||
* ${time} [${flag}]
|
||||
|
||||
${replaceStrings ["\n"] ["\n "] entry.message}
|
||||
''
|
||||
) env.newsEntries
|
||||
);
|
||||
|
||||
# File where each line corresponds to an unread news entry
|
||||
# identifier. If non-empty then the file ends in "\n".
|
||||
newsUnreadIdsFile = pkgs.writeText "news-unread-ids" (
|
||||
let
|
||||
text = concatMapStringsSep "\n" (entry: entry.id) newsFiltered;
|
||||
in
|
||||
text + optionalString (text != "") "\n"
|
||||
);
|
||||
|
||||
newsInfo = pkgs.writeText "news-info.sh" ''
|
||||
local newsNumUnread=${toString newsNumUnread}
|
||||
local newsDisplay="${env.newsDisplay}"
|
||||
local newsFileAll="${newsFileAll}"
|
||||
local newsFileUnread="${newsFileUnread}"
|
||||
local newsUnreadIdsFile="${newsUnreadIdsFile}"
|
||||
'';
|
||||
|
||||
in
|
||||
{
|
||||
inherit (env) activationPackage;
|
||||
inherit newsInfo;
|
||||
}
|
||||
84
home-manager/install.nix
Normal file
84
home-manager/install.nix
Normal file
@@ -0,0 +1,84 @@
|
||||
{ home-manager, runCommand }:
|
||||
|
||||
runCommand "home-manager-install" {
|
||||
propagatedBuildInputs = [ home-manager ];
|
||||
preferLocalBuild = true;
|
||||
allowSubstitutes = false;
|
||||
shellHookOnly = true;
|
||||
shellHook = ''
|
||||
confFile="''${XDG_CONFIG_HOME:-$HOME/.config}/nixpkgs/home.nix"
|
||||
|
||||
if [[ ! -e $confFile ]]; then
|
||||
echo
|
||||
echo "Creating initial Home Manager configuration..."
|
||||
|
||||
nl=$'\n'
|
||||
xdgVars=""
|
||||
if [[ -v XDG_CACHE_HOME && $XDG_CACHE_HOME != "$HOME/.cache" ]]; then
|
||||
xdgVars="$xdgVars xdg.cacheHome = \"$XDG_CACHE_HOME\";$nl"
|
||||
fi
|
||||
if [[ -v XDG_CONFIG_HOME && $XDG_CONFIG_HOME != "$HOME/.config" ]]; then
|
||||
xdgVars="$xdgVars xdg.configHome = \"$XDG_CONFIG_HOME\";$nl"
|
||||
fi
|
||||
if [[ -v XDG_DATA_HOME && $XDG_DATA_HOME != "$HOME/.local/share" ]]; then
|
||||
xdgVars="$xdgVars xdg.dataHome = \"$XDG_DATA_HOME\";$nl"
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$confFile")"
|
||||
cat > $confFile <<EOF
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
# Let Home Manager install and manage itself.
|
||||
programs.home-manager.enable = true;
|
||||
|
||||
# Home Manager needs a bit of information about you and the
|
||||
# paths it should manage.
|
||||
home.username = "$USER";
|
||||
home.homeDirectory = "$HOME";
|
||||
$xdgVars
|
||||
# This value determines the Home Manager release that your
|
||||
# configuration is compatible with. This helps avoid breakage
|
||||
# when a new Home Manager release introduces backwards
|
||||
# incompatible changes.
|
||||
#
|
||||
# You can update Home Manager without changing this value. See
|
||||
# the Home Manager release notes for a list of state version
|
||||
# changes in each release.
|
||||
home.stateVersion = "21.05";
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Creating initial Home Manager generation..."
|
||||
echo
|
||||
|
||||
if home-manager switch; then
|
||||
cat <<EOF
|
||||
|
||||
All done! The home-manager tool should now be installed and you
|
||||
can edit
|
||||
|
||||
$confFile
|
||||
|
||||
to configure Home Manager. Run 'man home-configuration.nix' to
|
||||
see all available options.
|
||||
EOF
|
||||
exit 0
|
||||
else
|
||||
cat <<EOF
|
||||
|
||||
Uh oh, the installation failed! Please create an issue at
|
||||
|
||||
https://github.com/nix-community/home-manager/issues
|
||||
|
||||
if the error seems to be the fault of Home Manager.
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
} ''
|
||||
echo This derivation is not buildable, instead run it using nix-shell.
|
||||
exit 1
|
||||
''
|
||||
396
modules/accounts/email.nix
Normal file
396
modules/accounts/email.nix
Normal file
@@ -0,0 +1,396 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.accounts.email;
|
||||
|
||||
gpgModule = types.submodule {
|
||||
options = {
|
||||
key = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The key to use as listed in <command>gpg --list-keys</command>.
|
||||
'';
|
||||
};
|
||||
|
||||
signByDefault = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Sign messages by default.";
|
||||
};
|
||||
|
||||
encryptByDefault = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Encrypt outgoing messages by default.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
signatureModule = types.submodule {
|
||||
options = {
|
||||
text = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = ''
|
||||
--
|
||||
Luke Skywalker
|
||||
May the force be with you.
|
||||
'';
|
||||
description = ''
|
||||
Signature content.
|
||||
'';
|
||||
};
|
||||
|
||||
showSignature = mkOption {
|
||||
type = types.enum [ "append" "attach" "none" ];
|
||||
default = "none";
|
||||
description = "Method to communicate the signature.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
tlsModule = types.submodule {
|
||||
options = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to enable TLS/SSL.
|
||||
'';
|
||||
};
|
||||
|
||||
useStartTls = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to use STARTTLS.
|
||||
'';
|
||||
};
|
||||
|
||||
certificatesFile = mkOption {
|
||||
type = types.path;
|
||||
default = config.accounts.email.certificatesFile;
|
||||
defaultText = "config.accounts.email.certificatesFile";
|
||||
description = ''
|
||||
Path to file containing certificate authorities that should
|
||||
be used to validate the connection authenticity. If
|
||||
<literal>null</literal> then the system default is used.
|
||||
Note, if set then the system default may still be accepted.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
imapModule = types.submodule {
|
||||
options = {
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
example = "imap.example.org";
|
||||
description = ''
|
||||
Hostname of IMAP server.
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.nullOr types.port;
|
||||
default = null;
|
||||
example = 993;
|
||||
description = ''
|
||||
The port on which the IMAP server listens. If
|
||||
<literal>null</literal> then the default port is used.
|
||||
'';
|
||||
};
|
||||
|
||||
tls = mkOption {
|
||||
type = tlsModule;
|
||||
default = { };
|
||||
description = ''
|
||||
Configuration for secure connections.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
smtpModule = types.submodule {
|
||||
options = {
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
example = "smtp.example.org";
|
||||
description = ''
|
||||
Hostname of SMTP server.
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.nullOr types.port;
|
||||
default = null;
|
||||
example = 465;
|
||||
description = ''
|
||||
The port on which the SMTP server listens. If
|
||||
<literal>null</literal> then the default port is used.
|
||||
'';
|
||||
};
|
||||
|
||||
tls = mkOption {
|
||||
type = tlsModule;
|
||||
default = { };
|
||||
description = ''
|
||||
Configuration for secure connections.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
maildirModule = types.submodule ({ config, ... }: {
|
||||
options = {
|
||||
path = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Path to maildir directory where mail for this account is
|
||||
stored. This is relative to the base maildir path.
|
||||
'';
|
||||
};
|
||||
|
||||
absPath = mkOption {
|
||||
type = types.path;
|
||||
readOnly = true;
|
||||
internal = true;
|
||||
default = "${cfg.maildirBasePath}/${config.path}";
|
||||
description = ''
|
||||
A convenience option whose value is the absolute path of
|
||||
this maildir.
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
mailAccountOpts = { name, config, ... }: {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
readOnly = true;
|
||||
description = ''
|
||||
Unique identifier of the account. This is set to the
|
||||
attribute name of the account configuration.
|
||||
'';
|
||||
};
|
||||
|
||||
primary = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether this is the primary account. Only one account may be
|
||||
set as primary.
|
||||
'';
|
||||
};
|
||||
|
||||
flavor = mkOption {
|
||||
type = types.enum [ "plain" "gmail.com" "runbox.com" ];
|
||||
default = "plain";
|
||||
description = ''
|
||||
Some email providers have peculiar behavior that require
|
||||
special treatment. This option is therefore intended to
|
||||
indicate the nature of the provider.
|
||||
</para><para>
|
||||
When this indicates a specific provider then, for example,
|
||||
the IMAP and SMTP server configuration may be set
|
||||
automatically.
|
||||
'';
|
||||
};
|
||||
|
||||
address = mkOption {
|
||||
type = types.strMatching ".*@.*";
|
||||
example = "jane.doe@example.org";
|
||||
description = "The email address of this account.";
|
||||
};
|
||||
|
||||
aliases = mkOption {
|
||||
type = types.listOf (types.strMatching ".*@.*");
|
||||
default = [ ];
|
||||
example = [ "webmaster@example.org" "admin@example.org" ];
|
||||
description = "Alternative email addresses of this account.";
|
||||
};
|
||||
|
||||
realName = mkOption {
|
||||
type = types.str;
|
||||
example = "Jane Doe";
|
||||
description = "Name displayed when sending mails.";
|
||||
};
|
||||
|
||||
userName = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
The server username of this account. This will be used as
|
||||
the SMTP and IMAP user name.
|
||||
'';
|
||||
};
|
||||
|
||||
passwordCommand = mkOption {
|
||||
type = types.nullOr (types.either types.str (types.listOf types.str));
|
||||
default = null;
|
||||
apply = p: if isString p then splitString " " p else p;
|
||||
example = "secret-tool lookup email me@example.org";
|
||||
description = ''
|
||||
A command, which when run writes the account password on
|
||||
standard output.
|
||||
'';
|
||||
};
|
||||
|
||||
folders = mkOption {
|
||||
type = types.submodule {
|
||||
options = {
|
||||
inbox = mkOption {
|
||||
type = types.str;
|
||||
default = "Inbox";
|
||||
description = ''
|
||||
Relative path of the inbox mail.
|
||||
'';
|
||||
};
|
||||
|
||||
sent = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "Sent";
|
||||
description = ''
|
||||
Relative path of the sent mail folder.
|
||||
'';
|
||||
};
|
||||
|
||||
drafts = mkOption {
|
||||
type = types.str;
|
||||
default = "Drafts";
|
||||
description = ''
|
||||
Relative path of the drafts mail folder.
|
||||
'';
|
||||
};
|
||||
|
||||
trash = mkOption {
|
||||
type = types.str;
|
||||
default = "Trash";
|
||||
description = ''
|
||||
Relative path of the deleted mail folder.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
description = ''
|
||||
Standard email folders.
|
||||
'';
|
||||
};
|
||||
|
||||
imap = mkOption {
|
||||
type = types.nullOr imapModule;
|
||||
default = null;
|
||||
description = ''
|
||||
The IMAP configuration to use for this account.
|
||||
'';
|
||||
};
|
||||
|
||||
signature = mkOption {
|
||||
type = signatureModule;
|
||||
default = { };
|
||||
description = ''
|
||||
Signature configuration.
|
||||
'';
|
||||
};
|
||||
|
||||
gpg = mkOption {
|
||||
type = types.nullOr gpgModule;
|
||||
default = null;
|
||||
description = ''
|
||||
GPG configuration.
|
||||
'';
|
||||
};
|
||||
|
||||
smtp = mkOption {
|
||||
type = types.nullOr smtpModule;
|
||||
default = null;
|
||||
description = ''
|
||||
The SMTP configuration to use for this account.
|
||||
'';
|
||||
};
|
||||
|
||||
maildir = mkOption {
|
||||
type = types.nullOr maildirModule;
|
||||
defaultText = { path = "\${name}"; };
|
||||
description = ''
|
||||
Maildir configuration for this account.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkMerge [
|
||||
{
|
||||
name = name;
|
||||
maildir = mkOptionDefault { path = "${name}"; };
|
||||
}
|
||||
|
||||
(mkIf (config.flavor == "gmail.com") {
|
||||
userName = mkDefault config.address;
|
||||
|
||||
imap = { host = "imap.gmail.com"; };
|
||||
|
||||
smtp = {
|
||||
host = "smtp.gmail.com";
|
||||
port = if config.smtp.tls.useStartTls then 587 else 465;
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf (config.flavor == "runbox.com") {
|
||||
imap = { host = "mail.runbox.com"; };
|
||||
|
||||
smtp = { host = "mail.runbox.com"; };
|
||||
})
|
||||
];
|
||||
};
|
||||
|
||||
in {
|
||||
options.accounts.email = {
|
||||
certificatesFile = mkOption {
|
||||
type = types.path;
|
||||
default = "/etc/ssl/certs/ca-certificates.crt";
|
||||
description = ''
|
||||
Path to default file containing certificate authorities that
|
||||
should be used to validate the connection authenticity. This
|
||||
path may be overridden on a per-account basis.
|
||||
'';
|
||||
};
|
||||
|
||||
maildirBasePath = mkOption {
|
||||
type = types.str;
|
||||
default = "${config.home.homeDirectory}/Maildir";
|
||||
defaultText = "$HOME/Maildir";
|
||||
apply = p:
|
||||
if hasPrefix "/" p then p else "${config.home.homeDirectory}/${p}";
|
||||
description = ''
|
||||
The base directory for account maildir directories. May be a
|
||||
relative path, in which case it is relative the home
|
||||
directory.
|
||||
'';
|
||||
};
|
||||
|
||||
accounts = mkOption {
|
||||
type = types.attrsOf (types.submodule mailAccountOpts);
|
||||
default = { };
|
||||
description = "List of email accounts.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf (cfg.accounts != { }) {
|
||||
assertions = [
|
||||
(let
|
||||
primaries =
|
||||
catAttrs "name" (filter (a: a.primary) (attrValues cfg.accounts));
|
||||
in {
|
||||
assertion = length primaries == 1;
|
||||
message = "Must have exactly one primary mail account but found "
|
||||
+ toString (length primaries) + optionalString (length primaries > 1)
|
||||
(", namely " + concatStringsSep ", " primaries);
|
||||
})
|
||||
];
|
||||
};
|
||||
}
|
||||
46
modules/config/i18n.nix
Normal file
46
modules/config/i18n.nix
Normal file
@@ -0,0 +1,46 @@
|
||||
# The glibc package in Nixpkgs is patched to make it possible to specify
|
||||
# an alternative path for the locale archive through a special environment
|
||||
# variable. This would allow different versions of glibc to coexist on the
|
||||
# same system because each version of glibc could look up different paths
|
||||
# for its locale archive should the archive format ever change in
|
||||
# incompatible ways.
|
||||
#
|
||||
# See also:
|
||||
# - localedef(1)
|
||||
# - https://nixos.org/manual/nixpkgs/stable/#locales
|
||||
# - https://github.com/NixOS/nixpkgs/issues/38991
|
||||
#
|
||||
# Note, the name of the said environment variable gets updated with each
|
||||
# breaking release of the glibcLocales package. Periodically check the link
|
||||
# below for changes:
|
||||
# https://github.com/NixOS/nixpkgs/blob/nixpkgs-unstable/pkgs/development/libraries/glibc/nix-locale-archive.patch
|
||||
|
||||
{ lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
inherit (pkgs.glibcLocales) version;
|
||||
|
||||
archivePath = "${pkgs.glibcLocales}/lib/locale/locale-archive";
|
||||
|
||||
# lookup the version of glibcLocales and set the appropriate environment vars
|
||||
localeVars = if versionAtLeast version "2.27" then {
|
||||
LOCALE_ARCHIVE_2_27 = archivePath;
|
||||
} else if versionAtLeast version "2.11" then {
|
||||
LOCALE_ARCHIVE_2_11 = archivePath;
|
||||
} else
|
||||
{ };
|
||||
|
||||
in {
|
||||
meta.maintainers = with maintainers; [ midchildan ];
|
||||
|
||||
config = {
|
||||
# For shell sessions.
|
||||
home.sessionVariables = localeVars;
|
||||
|
||||
# For desktop apps.
|
||||
systemd.user.sessionVariables = localeVars;
|
||||
};
|
||||
}
|
||||
@@ -1,46 +1,17 @@
|
||||
{ configuration
|
||||
, pkgs
|
||||
, lib ? pkgs.stdenv.lib
|
||||
, lib ? pkgs.lib
|
||||
|
||||
# Whether to check that each option has a matching declaration.
|
||||
, check ? true
|
||||
# Extra arguments passed to specialArgs.
|
||||
, extraSpecialArgs ? { }
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
modules = [
|
||||
./home-environment.nix
|
||||
./manual.nix
|
||||
./misc/gtk.nix
|
||||
./misc/pam.nix
|
||||
./programs/bash.nix
|
||||
./programs/beets.nix
|
||||
./programs/eclipse.nix
|
||||
./programs/emacs.nix
|
||||
./programs/firefox.nix
|
||||
./programs/git.nix
|
||||
./programs/gnome-terminal.nix
|
||||
./programs/info.nix
|
||||
./programs/lesspipe.nix
|
||||
./programs/ssh.nix
|
||||
./programs/texlive.nix
|
||||
./services/dunst.nix
|
||||
./services/gnome-keyring.nix
|
||||
./services/gpg-agent.nix
|
||||
./services/keepassx.nix
|
||||
./services/network-manager-applet.nix
|
||||
./services/random-background.nix
|
||||
./services/redshift.nix
|
||||
./services/taffybar.nix
|
||||
./services/tahoe-lafs.nix
|
||||
./services/udiskie.nix
|
||||
./services/xscreensaver.nix
|
||||
./systemd.nix
|
||||
./xresources.nix
|
||||
./xsession.nix
|
||||
<nixpkgs/nixos/modules/misc/assertions.nix>
|
||||
<nixpkgs/nixos/modules/misc/meta.nix>
|
||||
];
|
||||
|
||||
collectFailed = cfg:
|
||||
map (x: x.message) (filter (x: !x.assertion) cfg.assertions);
|
||||
|
||||
@@ -50,23 +21,28 @@ let
|
||||
in
|
||||
fold f res res.config.warnings;
|
||||
|
||||
pkgsModule = {
|
||||
config._module.args.pkgs = lib.mkForce pkgs;
|
||||
config._module.args.baseModules = modules;
|
||||
extendedLib = import ./lib/stdlib-extended.nix pkgs.lib;
|
||||
|
||||
hmModules =
|
||||
import ./modules.nix {
|
||||
inherit check pkgs;
|
||||
lib = extendedLib;
|
||||
};
|
||||
|
||||
rawModule = extendedLib.evalModules {
|
||||
modules = [ configuration ] ++ hmModules;
|
||||
specialArgs = {
|
||||
modulesPath = builtins.toString ./.;
|
||||
} // extraSpecialArgs;
|
||||
};
|
||||
|
||||
module = showWarnings (
|
||||
let
|
||||
mod = lib.evalModules {
|
||||
modules = [ configuration ] ++ modules ++ [ pkgsModule ];
|
||||
};
|
||||
|
||||
failed = collectFailed mod.config;
|
||||
|
||||
failed = collectFailed rawModule.config;
|
||||
failedStr = concatStringsSep "\n" (map (x: "- ${x}") failed);
|
||||
in
|
||||
if failed == []
|
||||
then mod
|
||||
then rawModule
|
||||
else throw "\nFailed assertions:\n${failedStr}"
|
||||
);
|
||||
|
||||
@@ -75,6 +51,14 @@ in
|
||||
{
|
||||
inherit (module) options config;
|
||||
|
||||
activationPackage = module.config.home.activationPackage;
|
||||
|
||||
# For backwards compatibility. Please use activationPackage instead.
|
||||
activation-script = module.config.home.activationPackage;
|
||||
home-path = module.config.home.path;
|
||||
|
||||
newsDisplay = rawModule.config.news.display;
|
||||
newsEntries =
|
||||
sort (a: b: a.time > b.time) (
|
||||
filter (a: a.condition) rawModule.config.news.entries
|
||||
);
|
||||
}
|
||||
|
||||
331
modules/files.nix
Normal file
331
modules/files.nix
Normal file
@@ -0,0 +1,331 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.home.file;
|
||||
|
||||
homeDirectory = config.home.homeDirectory;
|
||||
|
||||
fileType = (import lib/file-type.nix {
|
||||
inherit homeDirectory lib pkgs;
|
||||
}).fileType;
|
||||
|
||||
sourceStorePath = file:
|
||||
let
|
||||
sourcePath = toString file.source;
|
||||
sourceName = config.lib.strings.storeFileName (baseNameOf sourcePath);
|
||||
in
|
||||
if builtins.hasContext sourcePath
|
||||
then file.source
|
||||
else builtins.path { path = file.source; name = sourceName; };
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
options = {
|
||||
home.file = mkOption {
|
||||
description = "Attribute set of files to link into the user home.";
|
||||
default = {};
|
||||
type = fileType "<envar>HOME</envar>" homeDirectory;
|
||||
};
|
||||
|
||||
home-files = mkOption {
|
||||
type = types.package;
|
||||
internal = true;
|
||||
description = "Package to contain all home files";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
lib.file.mkOutOfStoreSymlink = path:
|
||||
let
|
||||
pathStr = toString path;
|
||||
name = hm.strings.storeFileName (baseNameOf pathStr);
|
||||
in
|
||||
pkgs.runCommandLocal name {} ''ln -s ${escapeShellArg pathStr} $out'';
|
||||
|
||||
# This verifies that the links we are about to create will not
|
||||
# overwrite an existing file.
|
||||
home.activation.checkLinkTargets = hm.dag.entryBefore ["writeBoundary"] (
|
||||
let
|
||||
# Paths that should be forcibly overwritten by Home Manager.
|
||||
# Caveat emptor!
|
||||
forcedPaths =
|
||||
concatMapStringsSep " " (p: ''"$HOME/${p}"'')
|
||||
(mapAttrsToList (n: v: v.target)
|
||||
(filterAttrs (n: v: v.force) cfg));
|
||||
|
||||
check = pkgs.writeText "check" ''
|
||||
. ${./lib-bash/color-echo.sh}
|
||||
|
||||
# A symbolic link whose target path matches this pattern will be
|
||||
# considered part of a Home Manager generation.
|
||||
homeFilePattern="$(readlink -e "${builtins.storeDir}")/*-home-manager-files/*"
|
||||
|
||||
forcedPaths=(${forcedPaths})
|
||||
|
||||
newGenFiles="$1"
|
||||
shift
|
||||
for sourcePath in "$@" ; do
|
||||
relativePath="''${sourcePath#$newGenFiles/}"
|
||||
targetPath="$HOME/$relativePath"
|
||||
|
||||
forced=""
|
||||
for forcedPath in "''${forcedPaths[@]}"; do
|
||||
if [[ $targetPath == $forcedPath* ]]; then
|
||||
forced="yeah"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -n $forced ]]; then
|
||||
$VERBOSE_ECHO "Skipping collision check for $targetPath"
|
||||
elif [[ -e "$targetPath" \
|
||||
&& ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then
|
||||
if [[ ! -L "$targetPath" && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then
|
||||
backup="$targetPath.$HOME_MANAGER_BACKUP_EXT"
|
||||
if [[ -e "$backup" ]]; then
|
||||
errorEcho "Existing file '$backup' would be clobbered by backing up '$targetPath'"
|
||||
collision=1
|
||||
else
|
||||
warnEcho "Existing file '$targetPath' is in the way of '$sourcePath', will be moved to '$backup'"
|
||||
fi
|
||||
else
|
||||
errorEcho "Existing file '$targetPath' is in the way of '$sourcePath'"
|
||||
collision=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -v collision ]] ; then
|
||||
errorEcho "Please move the above files and try again or use -b <ext> to move automatically."
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
in
|
||||
''
|
||||
function checkNewGenCollision() {
|
||||
local newGenFiles
|
||||
newGenFiles="$(readlink -e "$newGenPath/home-files")"
|
||||
find "$newGenFiles" \( -type f -or -type l \) \
|
||||
-exec bash ${check} "$newGenFiles" {} +
|
||||
}
|
||||
|
||||
checkNewGenCollision || exit 1
|
||||
''
|
||||
);
|
||||
|
||||
# This activation script will
|
||||
#
|
||||
# 1. Remove files from the old generation that are not in the new
|
||||
# generation.
|
||||
#
|
||||
# 2. Switch over the Home Manager gcroot and current profile
|
||||
# links.
|
||||
#
|
||||
# 3. Symlink files from the new generation into $HOME.
|
||||
#
|
||||
# This order is needed to ensure that we always know which links
|
||||
# belong to which generation. Specifically, if we're moving from
|
||||
# generation A to generation B having sets of home file links FA
|
||||
# and FB, respectively then cleaning before linking produces state
|
||||
# transitions similar to
|
||||
#
|
||||
# FA → FA ∩ FB → (FA ∩ FB) ∪ FB = FB
|
||||
#
|
||||
# and a failure during the intermediate state FA ∩ FB will not
|
||||
# result in lost links because this set of links are in both the
|
||||
# source and target generation.
|
||||
home.activation.linkGeneration = hm.dag.entryAfter ["writeBoundary"] (
|
||||
let
|
||||
link = pkgs.writeText "link" ''
|
||||
newGenFiles="$1"
|
||||
shift
|
||||
for sourcePath in "$@" ; do
|
||||
relativePath="''${sourcePath#$newGenFiles/}"
|
||||
targetPath="$HOME/$relativePath"
|
||||
if [[ -e "$targetPath" && ! -L "$targetPath" && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then
|
||||
backup="$targetPath.$HOME_MANAGER_BACKUP_EXT"
|
||||
$DRY_RUN_CMD mv $VERBOSE_ARG "$targetPath" "$backup" || errorEcho "Moving '$targetPath' failed!"
|
||||
fi
|
||||
$DRY_RUN_CMD mkdir -p $VERBOSE_ARG "$(dirname "$targetPath")"
|
||||
$DRY_RUN_CMD ln -nsf $VERBOSE_ARG "$sourcePath" "$targetPath"
|
||||
done
|
||||
'';
|
||||
|
||||
cleanup = pkgs.writeText "cleanup" ''
|
||||
. ${./lib-bash/color-echo.sh}
|
||||
|
||||
# A symbolic link whose target path matches this pattern will be
|
||||
# considered part of a Home Manager generation.
|
||||
homeFilePattern="$(readlink -e "${builtins.storeDir}")/*-home-manager-files/*"
|
||||
|
||||
newGenFiles="$1"
|
||||
shift 1
|
||||
for relativePath in "$@" ; do
|
||||
targetPath="$HOME/$relativePath"
|
||||
if [[ -e "$newGenFiles/$relativePath" ]] ; then
|
||||
$VERBOSE_ECHO "Checking $targetPath: exists"
|
||||
elif [[ ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then
|
||||
warnEcho "Path '$targetPath' does not link into a Home Manager generation. Skipping delete."
|
||||
else
|
||||
$VERBOSE_ECHO "Checking $targetPath: gone (deleting)"
|
||||
$DRY_RUN_CMD rm $VERBOSE_ARG "$targetPath"
|
||||
|
||||
# Recursively delete empty parent directories.
|
||||
targetDir="$(dirname "$relativePath")"
|
||||
if [[ "$targetDir" != "." ]] ; then
|
||||
pushd "$HOME" > /dev/null
|
||||
|
||||
# Call rmdir with a relative path excluding $HOME.
|
||||
# Otherwise, it might try to delete $HOME and exit
|
||||
# with a permission error.
|
||||
$DRY_RUN_CMD rmdir $VERBOSE_ARG \
|
||||
-p --ignore-fail-on-non-empty \
|
||||
"$targetDir"
|
||||
|
||||
popd > /dev/null
|
||||
fi
|
||||
fi
|
||||
done
|
||||
'';
|
||||
in
|
||||
''
|
||||
function linkNewGen() {
|
||||
echo "Creating home file links in $HOME"
|
||||
|
||||
local newGenFiles
|
||||
newGenFiles="$(readlink -e "$newGenPath/home-files")"
|
||||
find "$newGenFiles" \( -type f -or -type l \) \
|
||||
-exec bash ${link} "$newGenFiles" {} +
|
||||
}
|
||||
|
||||
function cleanOldGen() {
|
||||
if [[ ! -v oldGenPath ]] ; then
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Cleaning up orphan links from $HOME"
|
||||
|
||||
local newGenFiles oldGenFiles
|
||||
newGenFiles="$(readlink -e "$newGenPath/home-files")"
|
||||
oldGenFiles="$(readlink -e "$oldGenPath/home-files")"
|
||||
|
||||
# Apply the cleanup script on each leaf in the old
|
||||
# generation. The find command below will print the
|
||||
# relative path of the entry.
|
||||
find "$oldGenFiles" '(' -type f -or -type l ')' -printf '%P\0' \
|
||||
| xargs -0 bash ${cleanup} "$newGenFiles"
|
||||
}
|
||||
|
||||
cleanOldGen
|
||||
|
||||
if [[ ! -v oldGenPath || "$oldGenPath" != "$newGenPath" ]] ; then
|
||||
echo "Creating profile generation $newGenNum"
|
||||
$DRY_RUN_CMD nix-env $VERBOSE_ARG --profile "$genProfilePath" --set "$newGenPath"
|
||||
$DRY_RUN_CMD ln -Tsf $VERBOSE_ARG "$newGenPath" "$newGenGcPath"
|
||||
else
|
||||
echo "No change so reusing latest profile generation $oldGenNum"
|
||||
fi
|
||||
|
||||
linkNewGen
|
||||
''
|
||||
);
|
||||
|
||||
home.activation.checkFilesChanged = hm.dag.entryBefore ["linkGeneration"] (
|
||||
''
|
||||
declare -A changedFiles
|
||||
'' + concatMapStrings (v: ''
|
||||
cmp --quiet "${sourceStorePath v}" "${homeDirectory}/${v.target}" \
|
||||
&& changedFiles["${v.target}"]=0 \
|
||||
|| changedFiles["${v.target}"]=1
|
||||
'') (filter (v: v.onChange != "") (attrValues cfg))
|
||||
);
|
||||
|
||||
home.activation.onFilesChange = hm.dag.entryAfter ["linkGeneration"] (
|
||||
concatMapStrings (v: ''
|
||||
if [[ ${"$\{changedFiles"}["${v.target}"]} -eq 1 ]]; then
|
||||
${v.onChange}
|
||||
fi
|
||||
'') (filter (v: v.onChange != "") (attrValues cfg))
|
||||
);
|
||||
|
||||
# Symlink directories and files that have the right execute bit.
|
||||
# Copy files that need their execute bit changed.
|
||||
home-files = pkgs.runCommand
|
||||
"home-manager-files"
|
||||
{
|
||||
nativeBuildInputs = [ pkgs.xorg.lndir ];
|
||||
preferLocalBuild = true;
|
||||
allowSubstitutes = false;
|
||||
}
|
||||
(''
|
||||
mkdir -p $out
|
||||
|
||||
# Needed in case /nix is a symbolic link.
|
||||
realOut="$(realpath -m "$out")"
|
||||
|
||||
function insertFile() {
|
||||
local source="$1"
|
||||
local relTarget="$2"
|
||||
local executable="$3"
|
||||
local recursive="$4"
|
||||
|
||||
# Figure out the real absolute path to the target.
|
||||
local target
|
||||
target="$(realpath -m "$realOut/$relTarget")"
|
||||
|
||||
# Target path must be within $HOME.
|
||||
if [[ ! $target == $realOut* ]] ; then
|
||||
echo "Error installing file '$relTarget' outside \$HOME" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$target")"
|
||||
if [[ -d $source ]]; then
|
||||
if [[ $recursive ]]; then
|
||||
mkdir -p "$target"
|
||||
lndir -silent "$source" "$target"
|
||||
else
|
||||
ln -s "$source" "$target"
|
||||
fi
|
||||
else
|
||||
[[ -x $source ]] && isExecutable=1 || isExecutable=""
|
||||
|
||||
# Link the file into the home file directory if possible,
|
||||
# i.e., if the executable bit of the source is the same we
|
||||
# expect for the target. Otherwise, we copy the file and
|
||||
# set the executable bit to the expected value.
|
||||
if [[ $executable == inherit || $isExecutable == $executable ]]; then
|
||||
ln -s "$source" "$target"
|
||||
else
|
||||
cp "$source" "$target"
|
||||
|
||||
if [[ $executable == inherit ]]; then
|
||||
# Don't change file mode if it should match the source.
|
||||
:
|
||||
elif [[ $executable ]]; then
|
||||
chmod +x "$target"
|
||||
else
|
||||
chmod -x "$target"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
'' + concatStrings (
|
||||
mapAttrsToList (n: v: ''
|
||||
insertFile ${
|
||||
escapeShellArgs [
|
||||
(sourceStorePath v)
|
||||
v.target
|
||||
(if v.executable == null
|
||||
then "inherit"
|
||||
else toString v.executable)
|
||||
(toString v.recursive)
|
||||
]}
|
||||
'') cfg
|
||||
));
|
||||
};
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
with import ./lib/dag.nix;
|
||||
|
||||
let
|
||||
|
||||
@@ -17,11 +16,35 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
address = mkOption {
|
||||
ctype = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
description = ''
|
||||
The language to use for addresses.
|
||||
Character classification category.
|
||||
'';
|
||||
};
|
||||
|
||||
numeric = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
description = ''
|
||||
The language to use for numerical values.
|
||||
'';
|
||||
};
|
||||
|
||||
time = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
description = ''
|
||||
The language to use for formatting times.
|
||||
'';
|
||||
};
|
||||
|
||||
collate = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
description = ''
|
||||
The language to use for collation (alphabetical ordering).
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -33,6 +56,14 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
messages = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
description = ''
|
||||
The language to use for messages, application UI languages, etc.
|
||||
'';
|
||||
};
|
||||
|
||||
paper = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
@@ -41,29 +72,62 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
time = mkOption {
|
||||
name = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
description = ''
|
||||
The language to use for formatting times.
|
||||
The language to use for personal names.
|
||||
'';
|
||||
};
|
||||
|
||||
address = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
description = ''
|
||||
The language to use for addresses.
|
||||
'';
|
||||
};
|
||||
|
||||
telephone = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
description = ''
|
||||
The language to use for telephone numbers.
|
||||
'';
|
||||
};
|
||||
|
||||
measurement = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
description = ''
|
||||
The language to use for measurement values.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
keyboardSubModule = types.submodule {
|
||||
options = {
|
||||
layout = mkOption {
|
||||
type = types.str;
|
||||
default = "us";
|
||||
type = with types; nullOr str;
|
||||
default =
|
||||
if versionAtLeast config.home.stateVersion "19.09"
|
||||
then null
|
||||
else "us";
|
||||
defaultText = literalExample "null";
|
||||
description = ''
|
||||
Keyboard layout.
|
||||
Keyboard layout. If <literal>null</literal>, then the system
|
||||
configuration will be used.
|
||||
</para><para>
|
||||
This defaults to <literal>null</literal> for state
|
||||
version ≥ 19.09 and <literal>"us"</literal> otherwise.
|
||||
'';
|
||||
};
|
||||
|
||||
model = mkOption {
|
||||
type = types.str;
|
||||
default = "pc104";
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
example = "presario";
|
||||
description = ''
|
||||
Keyboard model.
|
||||
@@ -80,11 +144,19 @@ let
|
||||
};
|
||||
|
||||
variant = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
type = with types; nullOr str;
|
||||
default =
|
||||
if versionAtLeast config.home.stateVersion "19.09"
|
||||
then null
|
||||
else "";
|
||||
defaultText = literalExample "null";
|
||||
example = "colemak";
|
||||
description = ''
|
||||
X keyboard variant.
|
||||
X keyboard variant. If <literal>null</literal>, then the
|
||||
system configuration will be used.
|
||||
</para><para>
|
||||
This defaults to <literal>null</literal> for state
|
||||
version ≥ 19.09 and <literal>""</literal> otherwise.
|
||||
'';
|
||||
};
|
||||
};
|
||||
@@ -93,53 +165,51 @@ let
|
||||
in
|
||||
|
||||
{
|
||||
meta.maintainers = [ maintainers.rycee ];
|
||||
|
||||
imports = [
|
||||
(mkRemovedOptionModule [ "home" "sessionVariableSetter" ] ''
|
||||
Session variables are now always set through the shell. This is
|
||||
done automatically if the shell configuration is managed by Home
|
||||
Manager. If not, then you must source the
|
||||
|
||||
~/.nix-profile/etc/profile.d/hm-session-vars.sh
|
||||
|
||||
file yourself.
|
||||
'')
|
||||
];
|
||||
|
||||
options = {
|
||||
home.file = mkOption {
|
||||
description = "Attribute set of files to link into the user home.";
|
||||
default = {};
|
||||
type = types.loaOf (types.submodule (
|
||||
{ name, config, ... }: {
|
||||
options = {
|
||||
target = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Path to target file relative to <envar>HOME</envar>.
|
||||
'';
|
||||
};
|
||||
home.username = mkOption {
|
||||
type = types.str;
|
||||
defaultText = literalExample ''
|
||||
"$USER" for state version < 20.09,
|
||||
undefined for state version ≥ 20.09
|
||||
'';
|
||||
example = "jane.doe";
|
||||
description = "The user's username.";
|
||||
};
|
||||
|
||||
text = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.lines;
|
||||
description = "Text of the file.";
|
||||
};
|
||||
home.homeDirectory = mkOption {
|
||||
type = types.path;
|
||||
defaultText = literalExample ''
|
||||
"$HOME" for state version < 20.09,
|
||||
undefined for state version ≥ 20.09
|
||||
'';
|
||||
apply = toString;
|
||||
example = "/home/jane.doe";
|
||||
description = "The user's home directory. Must be an absolute path.";
|
||||
};
|
||||
|
||||
source = mkOption {
|
||||
type = types.path;
|
||||
description = ''
|
||||
Path of the source file. The file name must not start
|
||||
with a period since Nix will not allow such names in
|
||||
the Nix store.
|
||||
</para><para>
|
||||
This may refer to a directory.
|
||||
'';
|
||||
};
|
||||
|
||||
mode = mkOption {
|
||||
type = types.str;
|
||||
default = "444";
|
||||
description = "The permissions to apply to the file.";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
target = mkDefault name;
|
||||
source = mkIf (config.text != null) (
|
||||
let name' = "user-etc-" + baseNameOf name;
|
||||
in mkDefault (pkgs.writeText name' config.text)
|
||||
);
|
||||
};
|
||||
})
|
||||
);
|
||||
home.profileDirectory = mkOption {
|
||||
type = types.path;
|
||||
defaultText = "~/.nix-profile";
|
||||
internal = true;
|
||||
readOnly = true;
|
||||
description = ''
|
||||
The profile directory where Home Manager generations are
|
||||
installed.
|
||||
'';
|
||||
};
|
||||
|
||||
home.language = mkOption {
|
||||
@@ -149,9 +219,12 @@ in
|
||||
};
|
||||
|
||||
home.keyboard = mkOption {
|
||||
type = keyboardSubModule;
|
||||
type = types.nullOr keyboardSubModule;
|
||||
default = {};
|
||||
description = "Keyboard configuration.";
|
||||
description = ''
|
||||
Keyboard configuration. Set to <literal>null</literal> to
|
||||
disable Home Manager keyboard management.
|
||||
'';
|
||||
};
|
||||
|
||||
home.sessionVariables = mkOption {
|
||||
@@ -160,22 +233,55 @@ in
|
||||
example = { EDITOR = "emacs"; GS_OPTIONS = "-sPAPERSIZE=a4"; };
|
||||
description = ''
|
||||
Environment variables to always set at login.
|
||||
</para><para>
|
||||
The values may refer to other environment variables using
|
||||
POSIX.2 style variable references. For example, a variable
|
||||
<varname>parameter</varname> may be referenced as
|
||||
<code>$parameter</code> or <code>''${parameter}</code>. A
|
||||
default value <literal>foo</literal> may be given as per
|
||||
<code>''${parameter:-foo}</code> and, similarly, an alternate
|
||||
value <literal>bar</literal> can be given as per
|
||||
<code>''${parameter:+bar}</code>.
|
||||
</para><para>
|
||||
Note, these variables may be set in any order so no session
|
||||
variable may have a runtime dependency on another session
|
||||
variable. In particular code like
|
||||
<programlisting language="nix">
|
||||
home.sessionVariables = {
|
||||
FOO = "Hello";
|
||||
BAR = "$FOO World!";
|
||||
};
|
||||
</programlisting>
|
||||
may not work as expected. If you need to reference another
|
||||
session variable, then do so inside Nix instead. The above
|
||||
example then becomes
|
||||
<programlisting language="nix">
|
||||
home.sessionVariables = {
|
||||
FOO = "Hello";
|
||||
BAR = "''${config.home.sessionVariables.FOO} World!";
|
||||
};
|
||||
</programlisting>
|
||||
'';
|
||||
};
|
||||
|
||||
home.sessionVariableSetter = mkOption {
|
||||
default = "bash";
|
||||
type = types.enum [ "pam" "bash" ];
|
||||
example = "pam";
|
||||
home.sessionPath = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [ ];
|
||||
example = [
|
||||
".git/safe/../../bin"
|
||||
"\${xdg.configHome}/emacs/bin"
|
||||
"~/.local/bin"
|
||||
];
|
||||
description = "Extra directories to add to <envar>PATH</envar>.";
|
||||
};
|
||||
|
||||
home.sessionVariablesExtra = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
internal = true;
|
||||
description = ''
|
||||
Identifies the module that should set the session variables.
|
||||
</para><para>
|
||||
If "bash" is set then <varname>config.bash.enable</varname>
|
||||
must also be enabled.
|
||||
</para><para>
|
||||
If "pam" is set then PAM must be used to set the system
|
||||
environment. Also mind that typical environment variables
|
||||
might not be set by the time PAM starts up.
|
||||
Extra configuration to add to the
|
||||
<filename>hm-session-vars.sh</filename> file.
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -185,23 +291,79 @@ in
|
||||
description = "The set of packages to appear in the user environment.";
|
||||
};
|
||||
|
||||
home.extraOutputsToInstall = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = [ "doc" "info" "devdoc" ];
|
||||
description = ''
|
||||
List of additional package outputs of the packages
|
||||
<varname>home.packages</varname> that should be installed into
|
||||
the user environment.
|
||||
'';
|
||||
};
|
||||
|
||||
home.path = mkOption {
|
||||
internal = true;
|
||||
description = "The derivation installing the user packages.";
|
||||
};
|
||||
|
||||
home.activation = mkOption {
|
||||
home.emptyActivationPath = mkOption {
|
||||
internal = true;
|
||||
default = {};
|
||||
type = types.attrs;
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Activation scripts for the home environment.
|
||||
Whether the activation script should start with an empty
|
||||
<envar>PATH</envar> variable. When <literal>false</literal>
|
||||
then the user's <envar>PATH</envar> will be used.
|
||||
'';
|
||||
};
|
||||
|
||||
home.activation = mkOption {
|
||||
type = hm.types.dagOf types.str;
|
||||
default = {};
|
||||
example = literalExample ''
|
||||
{
|
||||
myActivationAction = lib.hm.dag.entryAfter ["writeBoundary"] '''
|
||||
$DRY_RUN_CMD ln -s $VERBOSE_ARG \
|
||||
''${builtins.toPath ./link-me-directly} $HOME
|
||||
''';
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
The activation scripts blocks to run when activating a Home
|
||||
Manager generation. Any entry here should be idempotent,
|
||||
meaning running twice or more times produces the same result
|
||||
as running it once.
|
||||
|
||||
</para><para>
|
||||
Any script should respect the <varname>DRY_RUN</varname>
|
||||
variable, if it is set then no actual action should be taken.
|
||||
|
||||
If the script block produces any observable side effect, such
|
||||
as writing or deleting files, then it
|
||||
<emphasis>must</emphasis> be placed after the special
|
||||
<literal>writeBoundary</literal> script block. Prior to the
|
||||
write boundary one can place script blocks that verifies, but
|
||||
does not modify, the state of the system and exits if an
|
||||
unexpected state is found. For example, the
|
||||
<literal>checkLinkTargets</literal> script block checks for
|
||||
collisions between non-managed files and files defined in
|
||||
<varname><link linkend="opt-home.file">home.file</link></varname>.
|
||||
|
||||
</para><para>
|
||||
|
||||
A script block should respect the <varname>DRY_RUN</varname>
|
||||
variable, if it is set then the actions taken by the script
|
||||
should be logged to standard out and not actually performed.
|
||||
The variable <varname>DRY_RUN_CMD</varname> is set to
|
||||
<code>echo</code> if dry run is enabled. Thus, many cases you
|
||||
can use the idiom <code>$DRY_RUN_CMD rm -rf /</code>.
|
||||
<command>echo</command> if dry run is enabled.
|
||||
|
||||
</para><para>
|
||||
|
||||
A script block should also respect the
|
||||
<varname>VERBOSE</varname> variable, and if set print
|
||||
information on standard out that may be useful for debugging
|
||||
any issue that may arise. The variable
|
||||
<varname>VERBOSE_ARG</varname> is set to
|
||||
<option>--verbose</option> if verbose output is enabled.
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -210,164 +372,138 @@ in
|
||||
type = types.package;
|
||||
description = "The package containing the complete activation script.";
|
||||
};
|
||||
|
||||
home.extraBuilderCommands = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
internal = true;
|
||||
description = ''
|
||||
Extra commands to run in the Home Manager generation builder.
|
||||
'';
|
||||
};
|
||||
|
||||
home.extraProfileCommands = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
internal = true;
|
||||
description = ''
|
||||
Extra commands to run in the Home Manager profile builder.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
assertions = [
|
||||
(let
|
||||
badFiles =
|
||||
filter (f: hasPrefix "." (baseNameOf f))
|
||||
(map (v: toString v.source)
|
||||
(attrValues cfg.file));
|
||||
badFilesStr = toString badFiles;
|
||||
in
|
||||
{
|
||||
assertion = badFiles == [];
|
||||
message = "Source file names must not start with '.': ${badFilesStr}";
|
||||
})
|
||||
{
|
||||
assertion = config.home.username != "";
|
||||
message = "Username could not be determined";
|
||||
}
|
||||
{
|
||||
assertion = config.home.homeDirectory != "";
|
||||
message = "Home directory could not be determined";
|
||||
}
|
||||
];
|
||||
|
||||
home.username =
|
||||
mkIf (versionOlder config.home.stateVersion "20.09")
|
||||
(mkDefault (builtins.getEnv "USER"));
|
||||
home.homeDirectory =
|
||||
mkIf (versionOlder config.home.stateVersion "20.09")
|
||||
(mkDefault (builtins.getEnv "HOME"));
|
||||
|
||||
home.profileDirectory =
|
||||
if config.submoduleSupport.enable
|
||||
&& config.submoduleSupport.externalPackageInstall
|
||||
then "/etc/profiles/per-user/${cfg.username}"
|
||||
else cfg.homeDirectory + "/.nix-profile";
|
||||
|
||||
home.sessionVariables =
|
||||
let
|
||||
maybeSet = name: value:
|
||||
listToAttrs (optional (value != null) { inherit name value; });
|
||||
maybeSet = n: v: optionalAttrs (v != null) { ${n} = v; };
|
||||
in
|
||||
(maybeSet "LANG" cfg.language.base)
|
||||
//
|
||||
(maybeSet "LC_ADDRESS" cfg.language.address)
|
||||
(maybeSet "LC_CTYPE" cfg.language.ctype)
|
||||
//
|
||||
(maybeSet "LC_NUMERIC" cfg.language.numeric)
|
||||
//
|
||||
(maybeSet "LC_TIME" cfg.language.time)
|
||||
//
|
||||
(maybeSet "LC_COLLATE" cfg.language.collate)
|
||||
//
|
||||
(maybeSet "LC_MONETARY" cfg.language.monetary)
|
||||
//
|
||||
(maybeSet "LC_MESSAGES" cfg.language.messages)
|
||||
//
|
||||
(maybeSet "LC_PAPER" cfg.language.paper)
|
||||
//
|
||||
(maybeSet "LC_TIME" cfg.language.time);
|
||||
(maybeSet "LC_NAME" cfg.language.name)
|
||||
//
|
||||
(maybeSet "LC_ADDRESS" cfg.language.address)
|
||||
//
|
||||
(maybeSet "LC_TELEPHONE" cfg.language.telephone)
|
||||
//
|
||||
(maybeSet "LC_MEASUREMENT" cfg.language.measurement);
|
||||
|
||||
home.packages = [
|
||||
# Provide a file holding all session variables.
|
||||
(
|
||||
pkgs.writeTextFile {
|
||||
name = "hm-session-vars.sh";
|
||||
destination = "/etc/profile.d/hm-session-vars.sh";
|
||||
text = ''
|
||||
# Only source this once.
|
||||
if [ -n "$__HM_SESS_VARS_SOURCED" ]; then return; fi
|
||||
export __HM_SESS_VARS_SOURCED=1
|
||||
|
||||
${config.lib.shell.exportAll cfg.sessionVariables}
|
||||
'' + lib.optionalString (cfg.sessionPath != [ ]) ''
|
||||
export PATH="$PATH''${PATH:+:}${concatStringsSep ":" cfg.sessionPath}"
|
||||
'' + cfg.sessionVariablesExtra;
|
||||
}
|
||||
)
|
||||
];
|
||||
|
||||
# A dummy entry acting as a boundary between the activation
|
||||
# script's "check" and the "write" phases.
|
||||
home.activation.writeBoundary = dagEntryAnywhere "";
|
||||
home.activation.writeBoundary = hm.dag.entryAnywhere "";
|
||||
|
||||
# This verifies that the links we are about to create will not
|
||||
# overwrite an existing file.
|
||||
home.activation.checkLinkTargets = dagEntryBefore ["writeBoundary"] (
|
||||
let
|
||||
pattern = "-home-manager-files/";
|
||||
check = pkgs.writeText "check" ''
|
||||
. ${./lib-bash/color-echo.sh}
|
||||
|
||||
newGenFiles="$1"
|
||||
shift
|
||||
for sourcePath in "$@" ; do
|
||||
relativePath="''${sourcePath#$newGenFiles/}"
|
||||
targetPath="$HOME/$relativePath"
|
||||
if [[ -e "$targetPath" \
|
||||
&& ! "$(readlink -e "$targetPath")" =~ "${pattern}" ]] ; then
|
||||
errorEcho "Existing file '$targetPath' is in the way"
|
||||
collision=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -v collision ]] ; then
|
||||
errorEcho "Please move the above files and try again"
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
in
|
||||
''
|
||||
function checkNewGenCollision() {
|
||||
local newGenFiles
|
||||
newGenFiles="$(readlink -e "$newGenPath/home-files")"
|
||||
find "$newGenFiles" -type f -print0 -or -type l -print0 \
|
||||
| xargs -0 bash ${check} "$newGenFiles"
|
||||
}
|
||||
|
||||
checkNewGenCollision || exit 1
|
||||
''
|
||||
);
|
||||
|
||||
home.activation.linkGeneration = dagEntryAfter ["writeBoundary"] (
|
||||
let
|
||||
pattern = "-home-manager-files/";
|
||||
|
||||
link = pkgs.writeText "link" ''
|
||||
newGenFiles="$1"
|
||||
shift
|
||||
for sourcePath in "$@" ; do
|
||||
relativePath="''${sourcePath#$newGenFiles/}"
|
||||
targetPath="$HOME/$relativePath"
|
||||
$DRY_RUN_CMD mkdir -p $VERBOSE_ARG "$(dirname "$targetPath")"
|
||||
$DRY_RUN_CMD ln -nsf $VERBOSE_ARG "$sourcePath" "$targetPath"
|
||||
done
|
||||
'';
|
||||
|
||||
cleanup = pkgs.writeText "cleanup" ''
|
||||
. ${./lib-bash/color-echo.sh}
|
||||
|
||||
newGenFiles="$1"
|
||||
oldGenFiles="$2"
|
||||
shift 2
|
||||
for sourcePath in "$@" ; do
|
||||
relativePath="''${sourcePath#$oldGenFiles/}"
|
||||
targetPath="$HOME/$relativePath"
|
||||
if [[ -e "$newGenFiles/$relativePath" ]] ; then
|
||||
$VERBOSE_ECHO "Checking $targetPath exists"
|
||||
elif [[ ! "$(readlink -e "$targetPath")" =~ "${pattern}" ]] ; then
|
||||
warnEcho "Path '$targetPath' not link into Home Manager generation. Skipping delete."
|
||||
else
|
||||
echo "Checking $targetPath gone (deleting)"
|
||||
$DRY_RUN_CMD rm $VERBOSE_ARG "$targetPath"
|
||||
$DRY_RUN_CMD rmdir --ignore-fail-on-non-empty \
|
||||
$VERBOSE_ARG -p "$(dirname "$targetPath")"
|
||||
fi
|
||||
done
|
||||
'';
|
||||
in
|
||||
# Install packages to the user environment.
|
||||
#
|
||||
# Note, sometimes our target may not allow modification of the Nix
|
||||
# store and then we cannot rely on `nix-env -i`. This is the case,
|
||||
# for example, if we are running as a NixOS module and building a
|
||||
# virtual machine. Then we must instead rely on an external
|
||||
# mechanism for installing packages, which in NixOS is provided by
|
||||
# the `users.users.<name?>.packages` option. The activation
|
||||
# command is still needed since some modules need to run their
|
||||
# activation commands after the packages are guaranteed to be
|
||||
# installed.
|
||||
#
|
||||
# In case the user has moved from a user-install of Home Manager
|
||||
# to a submodule managed one we attempt to uninstall the
|
||||
# `home-manager-path` package if it is installed.
|
||||
home.activation.installPackages = hm.dag.entryAfter ["writeBoundary"] (
|
||||
if config.submoduleSupport.externalPackageInstall
|
||||
then
|
||||
''
|
||||
function linkNewGen() {
|
||||
local newGenFiles
|
||||
newGenFiles="$(readlink -e "$newGenPath/home-files")"
|
||||
find "$newGenFiles" -type f -print0 -or -type l -print0 \
|
||||
| xargs -0 bash ${link} "$newGenFiles"
|
||||
}
|
||||
|
||||
function cleanOldGen() {
|
||||
if [[ ! -v oldGenPath ]] ; then
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Cleaning up orphan links from $HOME"
|
||||
|
||||
local newGenFiles oldGenFiles
|
||||
newGenFiles="$(readlink -e "$newGenPath/home-files")"
|
||||
oldGenFiles="$(readlink -e "$oldGenPath/home-files")"
|
||||
find "$oldGenFiles" -type f -print0 -or -type l -print0 \
|
||||
| xargs -0 bash ${cleanup} "$newGenFiles" "$oldGenFiles"
|
||||
}
|
||||
|
||||
if [[ ! -v oldGenPath || "$oldGenPath" != "$newGenPath" ]] ; then
|
||||
echo "Creating profile generation $newGenNum"
|
||||
$DRY_RUN_CMD ln -Tsf $VERBOSE_ARG "$newGenPath" "$newGenProfilePath"
|
||||
$DRY_RUN_CMD ln -Tsf $VERBOSE_ARG "$newGenProfilePath" "$genProfilePath"
|
||||
$DRY_RUN_CMD ln -Tsf $VERBOSE_ARG "$newGenPath" "$newGenGcPath"
|
||||
else
|
||||
echo "No change so reusing latest profile generation $oldGenNum"
|
||||
if nix-env -q | grep '^home-manager-path$'; then
|
||||
$DRY_RUN_CMD nix-env -e home-manager-path
|
||||
fi
|
||||
|
||||
linkNewGen
|
||||
cleanOldGen
|
||||
''
|
||||
else
|
||||
''
|
||||
$DRY_RUN_CMD nix-env -i ${cfg.path}
|
||||
''
|
||||
);
|
||||
|
||||
home.activation.installPackages = dagEntryAfter ["writeBoundary"] ''
|
||||
$DRY_RUN_CMD nix-env -i ${cfg.path}
|
||||
'';
|
||||
|
||||
home.activationPackage =
|
||||
let
|
||||
mkCmd = res: ''
|
||||
noteEcho Activating ${res.name}
|
||||
${res.data}
|
||||
'';
|
||||
sortedCommands = dagTopoSort cfg.activation;
|
||||
sortedCommands = hm.dag.topoSort cfg.activation;
|
||||
activationCmds =
|
||||
if sortedCommands ? result then
|
||||
concatStringsSep "\n" (map mkCmd sortedCommands.result)
|
||||
@@ -375,16 +511,28 @@ in
|
||||
abort ("Dependency cycle in activation script: "
|
||||
+ builtins.toJSON sortedCommands);
|
||||
|
||||
sf = pkgs.writeText "activation-script" ''
|
||||
#!${pkgs.stdenv.shell}
|
||||
# Programs that always should be available on the activation
|
||||
# script's PATH.
|
||||
activationBinPaths = lib.makeBinPath [
|
||||
pkgs.bash
|
||||
pkgs.coreutils
|
||||
pkgs.diffutils # For `cmp` and `diff`.
|
||||
pkgs.findutils
|
||||
pkgs.gnugrep
|
||||
pkgs.gnused
|
||||
pkgs.ncurses # For `tput`.
|
||||
]
|
||||
+ optionalString (!cfg.emptyActivationPath) "\${PATH:+:}$PATH";
|
||||
|
||||
activationScript = pkgs.writeScript "activation-script" ''
|
||||
#!${pkgs.runtimeShell}
|
||||
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
# This code explicitly requires GNU Core Utilities and Bash.
|
||||
# We therefore need to ensure they are prioritized over any
|
||||
# other similarly named tools on the system.
|
||||
export PATH="${pkgs.coreutils}/bin:${pkgs.bash}/bin:$PATH"
|
||||
cd $HOME
|
||||
|
||||
export PATH="${activationBinPaths}"
|
||||
|
||||
. ${./lib-bash/color-echo.sh}
|
||||
|
||||
@@ -392,47 +540,37 @@ in
|
||||
|
||||
${activationCmds}
|
||||
'';
|
||||
|
||||
home-files = pkgs.stdenv.mkDerivation {
|
||||
name = "home-manager-files";
|
||||
|
||||
phases = [ "installPhase" ];
|
||||
|
||||
installPhase =
|
||||
"mkdir -p $out\n" +
|
||||
concatStringsSep "\n" (
|
||||
mapAttrsToList (n: v:
|
||||
''
|
||||
if [ -d "${v.source}" ]; then
|
||||
mkdir -pv "$(dirname "$out/${v.target}")"
|
||||
ln -sv "${v.source}" "$out/${v.target}"
|
||||
else
|
||||
install -D -m${v.mode} "${v.source}" "$out/${v.target}"
|
||||
fi
|
||||
''
|
||||
) cfg.file
|
||||
);
|
||||
};
|
||||
in
|
||||
pkgs.stdenv.mkDerivation {
|
||||
name = "home-manager-generation";
|
||||
pkgs.runCommand
|
||||
"home-manager-generation"
|
||||
{
|
||||
preferLocalBuild = true;
|
||||
allowSubstitutes = false;
|
||||
}
|
||||
''
|
||||
mkdir -p $out
|
||||
|
||||
phases = [ "installPhase" ];
|
||||
cp ${activationScript} $out/activate
|
||||
|
||||
installPhase = ''
|
||||
install -D -m755 ${sf} $out/activate
|
||||
mkdir $out/bin
|
||||
ln -s $out/activate $out/bin/home-manager-generation
|
||||
|
||||
substituteInPlace $out/activate \
|
||||
--subst-var-by GENERATION_DIR $out
|
||||
|
||||
ln -s ${home-files} $out/home-files
|
||||
ln -s ${config.home-files} $out/home-files
|
||||
ln -s ${cfg.path} $out/home-path
|
||||
|
||||
${cfg.extraBuilderCommands}
|
||||
'';
|
||||
};
|
||||
|
||||
home.path = pkgs.buildEnv {
|
||||
name = "home-manager-path";
|
||||
|
||||
paths = cfg.packages;
|
||||
inherit (cfg) extraOutputsToInstall;
|
||||
|
||||
postBuild = cfg.extraProfileCommands;
|
||||
|
||||
meta = {
|
||||
description = "Environment of packages installed through home-manager";
|
||||
|
||||
@@ -1,35 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
function setupVars() {
|
||||
local profilesPath="/nix/var/nix/profiles/per-user/$USER"
|
||||
local gcPath="/nix/var/nix/gcroots/per-user/$USER"
|
||||
local nixStateDir="${NIX_STATE_DIR:-/nix/var/nix}"
|
||||
local profilesPath="$nixStateDir/profiles/per-user/$USER"
|
||||
local gcPath="$nixStateDir/gcroots/per-user/$USER"
|
||||
|
||||
genProfilePath="$profilesPath/home-manager"
|
||||
newGenPath="@GENERATION_DIR@";
|
||||
newGenGcPath="$gcPath/current-home"
|
||||
|
||||
local greatestGenNum
|
||||
|
||||
greatestGenNum=$( \
|
||||
find "$profilesPath" -name 'home-manager-*-link' \
|
||||
| sed 's/^.*-\([0-9]*\)-link$/\1/' \
|
||||
| sort -rn \
|
||||
| head -1)
|
||||
nix-env --list-generations --profile "$genProfilePath" \
|
||||
| tail -1 \
|
||||
| sed -E 's/ *([[:digit:]]+) .*/\1/')
|
||||
|
||||
if [[ -n "$greatestGenNum" ]] ; then
|
||||
if [[ -n $greatestGenNum ]] ; then
|
||||
oldGenNum=$greatestGenNum
|
||||
newGenNum=$((oldGenNum + 1))
|
||||
else
|
||||
newGenNum=1
|
||||
fi
|
||||
|
||||
if [[ -e "$gcPath/current-home" ]] ; then
|
||||
oldGenPath="$(readlink -e "$gcPath/current-home")"
|
||||
if [[ -e $profilesPath/home-manager ]] ; then
|
||||
oldGenPath="$(readlink -e "$profilesPath/home-manager")"
|
||||
fi
|
||||
|
||||
genProfilePath="$profilesPath/home-manager"
|
||||
newGenPath="@GENERATION_DIR@";
|
||||
newGenProfilePath="$profilesPath/home-manager-$newGenNum-link"
|
||||
newGenGcPath="$gcPath/current-home"
|
||||
$VERBOSE_ECHO "Sanity checking oldGenNum and oldGenPath"
|
||||
if [[ -v oldGenNum && ! -v oldGenPath
|
||||
|| ! -v oldGenNum && -v oldGenPath ]]; then
|
||||
errorEcho "Invalid profile number and current profile values! These"
|
||||
errorEcho "must be either both empty or both set but are now set to"
|
||||
errorEcho " '${oldGenNum:-}' and '${oldGenPath:-}'"
|
||||
errorEcho "If you don't mind losing previous profile generations then"
|
||||
errorEcho "the easiest solution is probably to run"
|
||||
errorEcho " rm $profilesPath/home-manager*"
|
||||
errorEcho " rm $gcPath/current-home"
|
||||
errorEcho "and trying home-manager switch again. Good luck!"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
setupVars
|
||||
|
||||
echo "Starting home manager activation"
|
||||
|
||||
if [[ -v VERBOSE ]]; then
|
||||
export VERBOSE_ECHO=echo
|
||||
export VERBOSE_ARG="--verbose"
|
||||
@@ -38,14 +49,28 @@ else
|
||||
export VERBOSE_ARG=""
|
||||
fi
|
||||
|
||||
echo "Starting home manager activation"
|
||||
|
||||
# Verify that we can connect to the Nix store and/or daemon. This will
|
||||
# also create the necessary directories in profiles and gcroots.
|
||||
$VERBOSE_ECHO "Sanity checking Nix"
|
||||
nix-build --expr '{}' --no-out-link
|
||||
|
||||
setupVars
|
||||
|
||||
if [[ -v DRY_RUN ]] ; then
|
||||
$VERBOSE_ECHO "This is a dry run"
|
||||
echo "This is a dry run"
|
||||
export DRY_RUN_CMD=echo
|
||||
else
|
||||
$VERBOSE_ECHO "This is a live run"
|
||||
export DRY_RUN_CMD=""
|
||||
fi
|
||||
|
||||
if [[ -v VERBOSE ]]; then
|
||||
echo -n "Using Nix version: "
|
||||
nix-env --version
|
||||
fi
|
||||
|
||||
$VERBOSE_ECHO "Activation variables:"
|
||||
if [[ -v oldGenNum ]] ; then
|
||||
$VERBOSE_ECHO " oldGenNum=$oldGenNum"
|
||||
@@ -56,6 +81,5 @@ else
|
||||
fi
|
||||
$VERBOSE_ECHO " newGenPath=$newGenPath"
|
||||
$VERBOSE_ECHO " newGenNum=$newGenNum"
|
||||
$VERBOSE_ECHO " newGenProfilePath=$newGenProfilePath"
|
||||
$VERBOSE_ECHO " newGenGcPath=$newGenGcPath"
|
||||
$VERBOSE_ECHO " genProfilePath=$genProfilePath"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# The check for terminal output and color support is heavily inspired
|
||||
# by https://unix.stackexchange.com/a/10065.
|
||||
#
|
||||
# Allow opt out by respecting the `NO_COLOR` environment variable.
|
||||
|
||||
function setupColors() {
|
||||
normalColor=""
|
||||
@@ -7,8 +9,8 @@ function setupColors() {
|
||||
warnColor=""
|
||||
noteColor=""
|
||||
|
||||
# Check if stdout is a terminal.
|
||||
if [[ -t 1 ]]; then
|
||||
# Enable colors for terminals, and allow opting out.
|
||||
if [[ ! -v NO_COLOR && -t 1 ]]; then
|
||||
# See if it supports colors.
|
||||
local ncolors
|
||||
ncolors=$(tput colors)
|
||||
|
||||
@@ -7,19 +7,17 @@
|
||||
# - the addition of the function `dagEntryBefore` indicating a
|
||||
# "wanted by" relationship.
|
||||
|
||||
with import <nixpkgs/lib/strings.nix>;
|
||||
with import <nixpkgs/lib/attrsets.nix>;
|
||||
with import <nixpkgs/lib/lists.nix>;
|
||||
{ lib }:
|
||||
|
||||
with lib;
|
||||
|
||||
rec {
|
||||
|
||||
emptyDag = {};
|
||||
emptyDag = { };
|
||||
|
||||
isDag = dag:
|
||||
let
|
||||
isEntry = e: (e ? data) && (e ? after) && (e ? before);
|
||||
in
|
||||
builtins.isAttrs dag && all (x: x) (mapAttrsToList (n: isEntry) dag);
|
||||
let isEntry = e: (e ? data) && (e ? after) && (e ? before);
|
||||
in builtins.isAttrs dag && all (x: x) (mapAttrsToList (n: isEntry) dag);
|
||||
|
||||
# Takes an attribute set containing entries built by
|
||||
# dagEntryAnywhere, dagEntryAfter, and dagEntryBefore to a
|
||||
@@ -80,22 +78,19 @@ rec {
|
||||
dagTopoSort = dag:
|
||||
let
|
||||
dagBefore = dag: name:
|
||||
mapAttrsToList (n: v: n) (
|
||||
filterAttrs (n: v: any (a: a == name) v.before) dag
|
||||
);
|
||||
normalizedDag =
|
||||
mapAttrs (n: v: {
|
||||
name = n;
|
||||
data = v.data;
|
||||
after = v.after ++ dagBefore dag n;
|
||||
}) dag;
|
||||
mapAttrsToList (n: v: n)
|
||||
(filterAttrs (n: v: any (a: a == name) v.before) dag);
|
||||
normalizedDag = mapAttrs (n: v: {
|
||||
name = n;
|
||||
data = v.data;
|
||||
after = v.after ++ dagBefore dag n;
|
||||
}) dag;
|
||||
before = a: b: any (c: a.name == c) b.after;
|
||||
sorted = toposort before (mapAttrsToList (n: v: v) normalizedDag);
|
||||
in
|
||||
if sorted ? result then
|
||||
{ result = map (v: { inherit (v) name data; }) sorted.result; }
|
||||
else
|
||||
sorted;
|
||||
in if sorted ? result then {
|
||||
result = map (v: { inherit (v) name data; }) sorted.result;
|
||||
} else
|
||||
sorted;
|
||||
|
||||
# Applies a function to each element of the given DAG.
|
||||
dagMap = f: dag: mapAttrs (n: v: v // { data = f n v.data; }) dag;
|
||||
@@ -103,22 +98,20 @@ rec {
|
||||
# Create a DAG entry with no particular dependency information.
|
||||
dagEntryAnywhere = data: {
|
||||
inherit data;
|
||||
before = [];
|
||||
after = [];
|
||||
before = [ ];
|
||||
after = [ ];
|
||||
};
|
||||
|
||||
dagEntryBetween = before: after: data: {
|
||||
inherit data before after;
|
||||
};
|
||||
dagEntryBetween = before: after: data: { inherit data before after; };
|
||||
|
||||
dagEntryAfter = after: data: {
|
||||
inherit data after;
|
||||
before = [];
|
||||
before = [ ];
|
||||
};
|
||||
|
||||
dagEntryBefore = before: data: {
|
||||
inherit data before;
|
||||
after = [];
|
||||
after = [ ];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
26
modules/lib/default.nix
Normal file
26
modules/lib/default.nix
Normal file
@@ -0,0 +1,26 @@
|
||||
{ lib }:
|
||||
|
||||
rec {
|
||||
dag =
|
||||
let
|
||||
d = import ./dag.nix { inherit lib; };
|
||||
in
|
||||
{
|
||||
empty = d.emptyDag;
|
||||
isDag = d.isDag;
|
||||
topoSort = d.dagTopoSort;
|
||||
map = d.dagMap;
|
||||
entryAnywhere = d.dagEntryAnywhere;
|
||||
entryBetween = d.dagEntryBetween;
|
||||
entryAfter = d.dagEntryAfter;
|
||||
entryBefore = d.dagEntryBefore;
|
||||
};
|
||||
|
||||
gvariant = import ./gvariant.nix { inherit lib; };
|
||||
maintainers = import ./maintainers.nix;
|
||||
strings = import ./strings.nix { inherit lib; };
|
||||
types = import ./types.nix { inherit dag gvariant lib; };
|
||||
|
||||
shell = import ./shell.nix { inherit lib; };
|
||||
zsh = import ./zsh.nix { inherit lib; };
|
||||
}
|
||||
112
modules/lib/file-type.nix
Normal file
112
modules/lib/file-type.nix
Normal file
@@ -0,0 +1,112 @@
|
||||
{ homeDirectory, lib, pkgs }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
# Constructs a type suitable for a `home.file` like option. The
|
||||
# target path may be either absolute or relative, in which case it
|
||||
# is relative the `basePath` argument (which itself must be an
|
||||
# absolute path).
|
||||
#
|
||||
# Arguments:
|
||||
# - basePathDesc docbook compatible description of the base path
|
||||
# - basePath the file base path
|
||||
fileType = basePathDesc: basePath: types.attrsOf (types.submodule (
|
||||
{ name, config, ... }: {
|
||||
options = {
|
||||
target = mkOption {
|
||||
type = types.str;
|
||||
apply = p:
|
||||
let
|
||||
absPath = if hasPrefix "/" p then p else "${basePath}/${p}";
|
||||
in
|
||||
removePrefix (homeDirectory + "/") absPath;
|
||||
defaultText = literalExample "<name>";
|
||||
description = ''
|
||||
Path to target file relative to ${basePathDesc}.
|
||||
'';
|
||||
};
|
||||
|
||||
text = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.lines;
|
||||
description = ''
|
||||
Text of the file. If this option is null then
|
||||
<link linkend="opt-home.file._name_.source">home.file.<name?>.source</link>
|
||||
must be set.
|
||||
'';
|
||||
};
|
||||
|
||||
source = mkOption {
|
||||
type = types.path;
|
||||
description = ''
|
||||
Path of the source file or directory. If
|
||||
<link linkend="opt-home.file._name_.text">home.file.<name?>.text</link>
|
||||
is non-null then this option will automatically point to a file
|
||||
containing that text.
|
||||
'';
|
||||
};
|
||||
|
||||
executable = mkOption {
|
||||
type = types.nullOr types.bool;
|
||||
default = null;
|
||||
description = ''
|
||||
Set the execute bit. If <literal>null</literal>, defaults to the mode
|
||||
of the <varname>source</varname> file or to <literal>false</literal>
|
||||
for files created through the <varname>text</varname> option.
|
||||
'';
|
||||
};
|
||||
|
||||
recursive = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
If the file source is a directory, then this option
|
||||
determines whether the directory should be recursively
|
||||
linked to the target location. This option has no effect
|
||||
if the source is a file.
|
||||
</para><para>
|
||||
If <literal>false</literal> (the default) then the target
|
||||
will be a symbolic link to the source directory. If
|
||||
<literal>true</literal> then the target will be a
|
||||
directory structure matching the source's but whose leafs
|
||||
are symbolic links to the files of the source directory.
|
||||
'';
|
||||
};
|
||||
|
||||
onChange = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Shell commands to run when file has changed between
|
||||
generations. The script will be run
|
||||
<emphasis>after</emphasis> the new files have been linked
|
||||
into place.
|
||||
'';
|
||||
};
|
||||
|
||||
force = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
visible = false;
|
||||
description = ''
|
||||
Whether the target path should be unconditionally replaced
|
||||
by the managed file source. Warning, this will silently
|
||||
delete the target regardless of whether it is a file or
|
||||
link.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
target = mkDefault name;
|
||||
source = mkIf (config.text != null) (
|
||||
mkDefault (pkgs.writeTextFile {
|
||||
inherit (config) executable text;
|
||||
name = hm.strings.storeFileName name;
|
||||
})
|
||||
);
|
||||
};
|
||||
}
|
||||
));
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
/* Functions that generate widespread file
|
||||
* formats from nix data structures.
|
||||
*
|
||||
* They all follow a similar interface:
|
||||
* generator { config-attrs } data
|
||||
*
|
||||
* Tests can be found in ./tests.nix
|
||||
* Documentation in the manual, #sec-generators
|
||||
*/
|
||||
with import <nixpkgs/lib/trivial.nix>;
|
||||
let
|
||||
libStr = import <nixpkgs/lib/strings.nix>;
|
||||
libAttr = import <nixpkgs/lib/attrsets.nix>;
|
||||
|
||||
flipMapAttrs = flip libAttr.mapAttrs;
|
||||
in
|
||||
|
||||
rec {
|
||||
|
||||
/* Generate a line of key k and value v, separated by
|
||||
* character sep. If sep appears in k, it is escaped.
|
||||
* Helper for synaxes with different separators.
|
||||
*
|
||||
* mkKeyValueDefault ":" "f:oo" "bar"
|
||||
* > "f\:oo:bar"
|
||||
*/
|
||||
mkKeyValueDefault = sep: k: v:
|
||||
"${libStr.escape [sep] k}${sep}${toString v}";
|
||||
|
||||
|
||||
/* Generate a key-value-style config file from an attrset.
|
||||
*
|
||||
* mkKeyValue is the same as in toINI.
|
||||
*/
|
||||
toKeyValue = {
|
||||
mkKeyValue ? mkKeyValueDefault "="
|
||||
}: attrs:
|
||||
let mkLine = k: v: mkKeyValue k v + "\n";
|
||||
in libStr.concatStrings (libAttr.mapAttrsToList mkLine attrs);
|
||||
|
||||
|
||||
/* Generate an INI-style config file from an
|
||||
* attrset of sections to an attrset of key-value pairs.
|
||||
*
|
||||
* generators.toINI {} {
|
||||
* foo = { hi = "${pkgs.hello}"; ciao = "bar"; };
|
||||
* baz = { "also, integers" = 42; };
|
||||
* }
|
||||
*
|
||||
*> [baz]
|
||||
*> also, integers=42
|
||||
*>
|
||||
*> [foo]
|
||||
*> ciao=bar
|
||||
*> hi=/nix/store/y93qql1p5ggfnaqjjqhxcw0vqw95rlz0-hello-2.10
|
||||
*
|
||||
* The mk* configuration attributes can generically change
|
||||
* the way sections and key-value strings are generated.
|
||||
*
|
||||
* For more examples see the test cases in ./tests.nix.
|
||||
*/
|
||||
toINI = {
|
||||
# apply transformations (e.g. escapes) to section names
|
||||
mkSectionName ? (name: libStr.escape [ "[" "]" ] name),
|
||||
# format a setting line from key and value
|
||||
mkKeyValue ? mkKeyValueDefault "="
|
||||
}: attrsOfAttrs:
|
||||
let
|
||||
# map function to string for each key val
|
||||
mapAttrsToStringsSep = sep: mapFn: attrs:
|
||||
libStr.concatStringsSep sep
|
||||
(libAttr.mapAttrsToList mapFn attrs);
|
||||
mkSection = sectName: sectValues: ''
|
||||
[${mkSectionName sectName}]
|
||||
'' + toKeyValue { inherit mkKeyValue; } sectValues;
|
||||
in
|
||||
# map input to ini sections
|
||||
mapAttrsToStringsSep "\n" mkSection attrsOfAttrs;
|
||||
|
||||
|
||||
/* Generates JSON from an arbitrary (non-function) value.
|
||||
* For more information see the documentation of the builtin.
|
||||
*/
|
||||
toJSON = {}: builtins.toJSON;
|
||||
|
||||
|
||||
/* YAML has been a strict superset of JSON since 1.2, so we
|
||||
* use toJSON. Before it only had a few differences referring
|
||||
* to implicit typing rules, so it should work with older
|
||||
* parsers as well.
|
||||
*/
|
||||
toYAML = {}@args: toJSON args;
|
||||
}
|
||||
156
modules/lib/gvariant.nix
Normal file
156
modules/lib/gvariant.nix
Normal file
@@ -0,0 +1,156 @@
|
||||
# A partial and basic implementation of GVariant formatted strings.
|
||||
#
|
||||
# Note, this API is not considered fully stable and it might therefore
|
||||
# change in backwards incompatible ways without prior notice.
|
||||
|
||||
{ lib }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
mkPrimitive = t: v: {
|
||||
_type = "gvariant";
|
||||
type = t;
|
||||
value = v;
|
||||
__toString = self: "@${self.type} ${toString self.value}";
|
||||
};
|
||||
|
||||
type = {
|
||||
arrayOf = t: "a${t}";
|
||||
maybeOf = t: "m${t}";
|
||||
tupleOf = ts: "(${concatStrings ts})";
|
||||
string = "s";
|
||||
boolean = "b";
|
||||
uchar = "y";
|
||||
int16 = "n";
|
||||
uint16 = "q";
|
||||
int32 = "i";
|
||||
uint32 = "u";
|
||||
int64 = "x";
|
||||
uint64 = "t";
|
||||
double = "d";
|
||||
};
|
||||
|
||||
# Returns the GVariant type of a given Nix value. If no type can be
|
||||
# found for the value then the empty string is returned.
|
||||
typeOf = v:
|
||||
with type;
|
||||
if builtins.isBool v then
|
||||
boolean
|
||||
else if builtins.isInt v then
|
||||
int32
|
||||
else if builtins.isFloat v then
|
||||
double
|
||||
else if builtins.isString v then
|
||||
string
|
||||
else if builtins.isList v then
|
||||
let elemType = elemTypeOf v;
|
||||
in if elemType == "" then "" else arrayOf elemType
|
||||
else if builtins.isAttrs v && v ? type then
|
||||
v.type
|
||||
else
|
||||
"";
|
||||
|
||||
elemTypeOf = vs:
|
||||
if builtins.isList vs then
|
||||
if vs == [ ] then "" else typeOf (head vs)
|
||||
else
|
||||
"";
|
||||
|
||||
mkMaybe = elemType: elem:
|
||||
mkPrimitive (type.maybeOf elemType) elem // {
|
||||
__toString = self:
|
||||
if self.value == null then
|
||||
"@${self.type} nothing"
|
||||
else
|
||||
"just ${toString self.value}";
|
||||
};
|
||||
|
||||
in rec {
|
||||
|
||||
inherit type typeOf;
|
||||
|
||||
isArray = hasPrefix "a";
|
||||
isMaybe = hasPrefix "m";
|
||||
isTuple = hasPrefix "(";
|
||||
|
||||
# Returns the GVariant value that most closely matches the given Nix
|
||||
# value. If no GVariant value can be found then `null` is returned.
|
||||
#
|
||||
# No support for dictionaries, maybe types, or variants.
|
||||
mkValue = v:
|
||||
if builtins.isBool v then
|
||||
mkBoolean v
|
||||
else if builtins.isInt v then
|
||||
mkInt32 v
|
||||
else if builtins.isFloat v then
|
||||
mkDouble v
|
||||
else if builtins.isString v then
|
||||
mkString v
|
||||
else if builtins.isList v then
|
||||
if v == [ ] then mkArray type.string [ ] else mkArray (elemTypeOf v) v
|
||||
else if builtins.isAttrs v && (v._type or "") == "gvariant" then
|
||||
v
|
||||
else
|
||||
null;
|
||||
|
||||
mkArray = elemType: elems:
|
||||
mkPrimitive (type.arrayOf elemType) (map mkValue elems) // {
|
||||
__toString = self:
|
||||
"@${self.type} [${concatMapStringsSep "," toString self.value}]";
|
||||
};
|
||||
|
||||
mkEmptyArray = elemType: mkArray elemType [ ];
|
||||
|
||||
mkNothing = elemType: mkMaybe elemType null;
|
||||
|
||||
mkJust = elem: let gvarElem = mkValue elem; in mkMaybe gvarElem.type gvarElem;
|
||||
|
||||
mkTuple = elems:
|
||||
let
|
||||
gvarElems = map mkValue elems;
|
||||
tupleType = type.tupleOf (map (e: e.type) gvarElems);
|
||||
in mkPrimitive tupleType gvarElems // {
|
||||
__toString = self:
|
||||
"@${self.type} (${concatMapStringsSep "," toString self.value})";
|
||||
};
|
||||
|
||||
mkBoolean = v:
|
||||
mkPrimitive type.boolean v // {
|
||||
__toString = self: if self.value then "true" else "false";
|
||||
};
|
||||
|
||||
mkString = v:
|
||||
mkPrimitive type.string v // {
|
||||
__toString = self: "'${escape [ "'" "\\" ] self.value}'";
|
||||
};
|
||||
|
||||
mkObjectpath = v:
|
||||
mkPrimitive type.string v // {
|
||||
__toString = self: "objectpath '${escape [ "'" ] self.value}'";
|
||||
};
|
||||
|
||||
mkUchar = mkPrimitive type.uchar;
|
||||
|
||||
mkInt16 = mkPrimitive type.int16;
|
||||
|
||||
mkUint16 = mkPrimitive type.uint16;
|
||||
|
||||
mkInt32 = v:
|
||||
mkPrimitive type.int32 v // {
|
||||
__toString = self: toString self.value;
|
||||
};
|
||||
|
||||
mkUint32 = mkPrimitive type.uint32;
|
||||
|
||||
mkInt64 = mkPrimitive type.int64;
|
||||
|
||||
mkUint64 = mkPrimitive type.uint64;
|
||||
|
||||
mkDouble = v:
|
||||
mkPrimitive type.double v // {
|
||||
__toString = self: toString self.value;
|
||||
};
|
||||
|
||||
}
|
||||
68
modules/lib/maintainers.nix
Normal file
68
modules/lib/maintainers.nix
Normal file
@@ -0,0 +1,68 @@
|
||||
# Home Manager maintainers.
|
||||
#
|
||||
# This attribute set contains Home Manager module maintainers that do
|
||||
# not have an entry in the Nixpkgs maintainer list [1]. Entries here
|
||||
# are expected to be follow the same format as described in [1].
|
||||
#
|
||||
# [1] https://github.com/NixOS/nixpkgs/blob/fca0d6e093c82b31103dc0dacc48da2a9b06e24b/maintainers/maintainer-list.nix#LC1
|
||||
|
||||
{
|
||||
justinlovinger = {
|
||||
name = "Justin Lovinger";
|
||||
email = "git@justinlovinger.com";
|
||||
github = "JustinLovinger";
|
||||
githubId = 7183441;
|
||||
};
|
||||
owm111 = {
|
||||
email = "7798336+owm111@users.noreply.github.com";
|
||||
name = "Owen McGrath";
|
||||
github = "owm111";
|
||||
githubId = 7798336;
|
||||
};
|
||||
cwyc = {
|
||||
email = "cwyc@users.noreply.github.com";
|
||||
name = "cwyc";
|
||||
github = "cwyc";
|
||||
githubId = 16950437;
|
||||
};
|
||||
olmokramer = {
|
||||
name = "Olmo Kramer";
|
||||
email = "olmokramer@users.noreply.github.com";
|
||||
github = "olmokramer";
|
||||
githubId = 3612514;
|
||||
};
|
||||
kubukoz = {
|
||||
name = "Jakub Kozłowski";
|
||||
email = "kubukoz@users.noreply.github.com";
|
||||
github = "kubukoz";
|
||||
githubId = 894884;
|
||||
};
|
||||
matrss = {
|
||||
name = "Matthias Riße";
|
||||
email = "matrss@users.noreply.github.com";
|
||||
github = "matrss";
|
||||
githubId = 9308656;
|
||||
};
|
||||
seylerius = {
|
||||
email = "sable@seyleri.us";
|
||||
name = "Sable Seyler";
|
||||
github = "seylerius";
|
||||
githubId = 1145981;
|
||||
keys = [{
|
||||
logkeyid = "rsa4096/0x68BF2EAE6D91CAFF";
|
||||
fingerprint = "F0E0 0311 126A CD72 4392 25E6 68BF 2EAE 6D91 CAFF";
|
||||
}];
|
||||
};
|
||||
thiagokokada = {
|
||||
email = "thiagokokada@gmail.com";
|
||||
name = "Thiago Kenji Okada";
|
||||
github = "thiagokokada";
|
||||
githubId = 844343;
|
||||
};
|
||||
fendse = {
|
||||
email = "46252070+Fendse@users.noreply.github.com";
|
||||
github = "Fendse";
|
||||
githubId = 46252070;
|
||||
name = "Sara Johnsson";
|
||||
};
|
||||
}
|
||||
11
modules/lib/shell.nix
Normal file
11
modules/lib/shell.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
{ lib }:
|
||||
|
||||
rec {
|
||||
# Produces a Bourne shell like variable export statement.
|
||||
export = n: v: ''export ${n}="${toString v}"'';
|
||||
|
||||
# Given an attribute set containing shell variable names and their
|
||||
# assignment, this function produces a string containing an export
|
||||
# statement for each set entry.
|
||||
exportAll = vars: lib.concatStringsSep "\n" (lib.mapAttrsToList export vars);
|
||||
}
|
||||
7
modules/lib/stdlib-extended.nix
Normal file
7
modules/lib/stdlib-extended.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
# Just a convenience function that returns the given Nixpkgs standard
|
||||
# library extended with the HM library.
|
||||
|
||||
nixpkgsLib:
|
||||
|
||||
let mkHmLib = import ./.;
|
||||
in nixpkgsLib.extend (self: super: { hm = mkHmLib { lib = super; }; })
|
||||
22
modules/lib/strings.nix
Normal file
22
modules/lib/strings.nix
Normal file
@@ -0,0 +1,22 @@
|
||||
{ lib }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
# Figures out a valid Nix store name for the given path.
|
||||
storeFileName = path:
|
||||
let
|
||||
# All characters that are considered safe. Note "-" is not
|
||||
# included to avoid "-" followed by digit being interpreted as a
|
||||
# version.
|
||||
safeChars = [ "+" "." "_" "?" "=" ] ++ lowerChars ++ upperChars
|
||||
++ stringToCharacters "0123456789";
|
||||
|
||||
empties = l: genList (x: "") (length l);
|
||||
|
||||
unsafeInName =
|
||||
stringToCharacters (replaceStrings safeChars (empties safeChars) path);
|
||||
|
||||
safeName = replaceStrings unsafeInName (empties unsafeInName) path;
|
||||
in "hm_" + safeName;
|
||||
}
|
||||
99
modules/lib/types-dag.nix
Normal file
99
modules/lib/types-dag.nix
Normal file
@@ -0,0 +1,99 @@
|
||||
{ dag, lib }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
isDagEntry = e: isAttrs e && (e ? data) && (e ? after) && (e ? before);
|
||||
|
||||
dagContentType = elemType:
|
||||
types.submodule ({ name, ... }: {
|
||||
options = {
|
||||
data = mkOption { type = elemType; };
|
||||
after = mkOption { type = with types; uniq (listOf str); };
|
||||
before = mkOption { type = with types; uniq (listOf str); };
|
||||
};
|
||||
config = mkIf (elemType.name == "submodule") {
|
||||
data._module.args.dagName = name;
|
||||
};
|
||||
});
|
||||
|
||||
in rec {
|
||||
# A directed acyclic graph of some inner type.
|
||||
#
|
||||
# Note, if the element type is a submodule then the `name` argument
|
||||
# will always be set to the string "data" since it picks up the
|
||||
# internal structure of the DAG values. To give access to the
|
||||
# "actual" attribute name a new submodule argument is provided with
|
||||
# the name `dagName`.
|
||||
dagOf = elemType:
|
||||
let
|
||||
convertAllToDags = let
|
||||
maybeConvert = n: v: if isDagEntry v then v else dag.entryAnywhere v;
|
||||
in map (def: def // { value = mapAttrs maybeConvert def.value; });
|
||||
|
||||
attrEquivalent = types.attrsOf (dagContentType elemType);
|
||||
in mkOptionType rec {
|
||||
name = "dagOf";
|
||||
description = "DAG of ${elemType.description}s";
|
||||
check = isAttrs;
|
||||
merge = loc: defs: attrEquivalent.merge loc (convertAllToDags defs);
|
||||
getSubOptions = prefix: elemType.getSubOptions (prefix ++ [ "<name>" ]);
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: dagOf (elemType.substSubModules m);
|
||||
functor = (defaultFunctor name) // { wrapped = elemType; };
|
||||
};
|
||||
|
||||
# A directed acyclic graph of some inner type OR a list of that
|
||||
# inner type. This is a temporary hack for use by the
|
||||
# `programs.ssh.matchBlocks` and is only guaranteed to be vaguely
|
||||
# correct!
|
||||
#
|
||||
# In particular, adding a dependency on one of the "unnamed-N-M"
|
||||
# entries generated by a list value is almost guaranteed to destroy
|
||||
# the list's order.
|
||||
#
|
||||
# This function will be removed in version 20.09.
|
||||
listOrDagOf = elemType:
|
||||
let
|
||||
paddedIndexStr = list: i:
|
||||
let padWidth = stringLength (toString (length list));
|
||||
in fixedWidthNumber padWidth i;
|
||||
|
||||
convertAll = loc: defs:
|
||||
let
|
||||
convertListValue = namePrefix: def:
|
||||
let
|
||||
vs = def.value;
|
||||
pad = paddedIndexStr vs;
|
||||
makeEntry = i: v: nameValuePair "${namePrefix}.${pad i}" v;
|
||||
warning = ''
|
||||
In file ${def.file}
|
||||
a list is being assigned to the option '${
|
||||
concatStringsSep "." loc
|
||||
}'.
|
||||
This will soon be an error due to the list form being deprecated.
|
||||
Please use the attribute set form instead with DAG functions to
|
||||
express the desired order of entries.
|
||||
'';
|
||||
in warn warning (listToAttrs (imap1 makeEntry vs));
|
||||
|
||||
convertValue = i: def:
|
||||
if isList def.value then
|
||||
convertListValue "unnamed-${paddedIndexStr defs i}" def
|
||||
else
|
||||
def.value;
|
||||
in imap1 (i: def: def // { value = convertValue i def; }) defs;
|
||||
|
||||
dagType = dagOf elemType;
|
||||
in mkOptionType rec {
|
||||
name = "listOrDagOf";
|
||||
description = "list or DAG of ${elemType.description}s";
|
||||
check = x: isList x || dagType.check x;
|
||||
merge = loc: defs: dagType.merge loc (convertAll loc defs);
|
||||
getSubOptions = dagType.getSubOptions;
|
||||
getSubModules = dagType.getSubModules;
|
||||
substSubModules = m: listOrDagOf (elemType.substSubModules m);
|
||||
functor = (defaultFunctor name) // { wrapped = elemType; };
|
||||
};
|
||||
}
|
||||
99
modules/lib/types.nix
Normal file
99
modules/lib/types.nix
Normal file
@@ -0,0 +1,99 @@
|
||||
{ lib, dag ? import ./dag.nix { inherit lib; }
|
||||
, gvariant ? import ./gvariant.nix { inherit lib; } }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
typesDag = import ./types-dag.nix { inherit dag lib; };
|
||||
|
||||
# Needed since the type is called gvariant and its merge attribute
|
||||
# must refer back to the type.
|
||||
gvar = gvariant;
|
||||
|
||||
in rec {
|
||||
|
||||
inherit (typesDag) dagOf listOrDagOf;
|
||||
|
||||
selectorFunction = mkOptionType {
|
||||
name = "selectorFunction";
|
||||
description = "Function that takes an attribute set and returns a list"
|
||||
+ " containing a selection of the values of the input set";
|
||||
check = isFunction;
|
||||
merge = _loc: defs: as: concatMap (select: select as) (getValues defs);
|
||||
};
|
||||
|
||||
overlayFunction = mkOptionType {
|
||||
name = "overlayFunction";
|
||||
description = "An overlay function, takes self and super and returns"
|
||||
+ " an attribute set overriding the desired attributes.";
|
||||
check = isFunction;
|
||||
merge = _loc: defs: self: super:
|
||||
foldl' (res: def: mergeAttrs res (def.value self super)) { } defs;
|
||||
};
|
||||
|
||||
fontType = types.submodule {
|
||||
options = {
|
||||
package = mkOption {
|
||||
type = types.nullOr types.package;
|
||||
default = null;
|
||||
example = literalExample "pkgs.dejavu_fonts";
|
||||
description = ''
|
||||
Package providing the font. This package will be installed
|
||||
to your profile. If <literal>null</literal> then the font
|
||||
is assumed to already be available in your profile.
|
||||
'';
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
example = "DejaVu Sans";
|
||||
description = ''
|
||||
The family name of the font within the package.
|
||||
'';
|
||||
};
|
||||
|
||||
size = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
example = "8";
|
||||
description = ''
|
||||
The size of the font.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
gvariant = mkOptionType rec {
|
||||
name = "gvariant";
|
||||
description = "GVariant value";
|
||||
check = v: gvar.mkValue v != null;
|
||||
merge = loc: defs:
|
||||
let
|
||||
vdefs = map (d: d // { value = gvar.mkValue d.value; }) defs;
|
||||
vals = map (d: d.value) vdefs;
|
||||
defTypes = map (x: x.type) vals;
|
||||
sameOrNull = x: y: if x == y then y else null;
|
||||
# A bit naive to just check the first entry…
|
||||
sharedDefType = foldl' sameOrNull (head defTypes) defTypes;
|
||||
allChecked = all (x: check x) vals;
|
||||
in if sharedDefType == null then
|
||||
throw ("Cannot merge definitions of `${showOption loc}' with"
|
||||
+ " mismatched GVariant types given in"
|
||||
+ " ${showFiles (getFiles defs)}.")
|
||||
else if gvar.isArray sharedDefType && allChecked then
|
||||
(types.listOf gvariant).merge loc
|
||||
(map (d: d // { value = d.value.value; }) vdefs)
|
||||
else if gvar.isTuple sharedDefType && allChecked then
|
||||
mergeOneOption loc defs
|
||||
else if gvar.isMaybe sharedDefType && allChecked then
|
||||
mergeOneOption loc defs
|
||||
else if gvar.type.string == sharedDefType && allChecked then
|
||||
types.str.merge loc defs
|
||||
else if gvar.type.double == sharedDefType && allChecked then
|
||||
types.float.merge loc defs
|
||||
else
|
||||
mergeDefaultOption loc defs;
|
||||
};
|
||||
|
||||
}
|
||||
30
modules/lib/zsh.nix
Normal file
30
modules/lib/zsh.nix
Normal file
@@ -0,0 +1,30 @@
|
||||
{ lib }:
|
||||
|
||||
rec {
|
||||
# Produces a Zsh shell like value
|
||||
toZshValue = v:
|
||||
if builtins.isBool v then
|
||||
if v then "true" else "false"
|
||||
else if builtins.isString v then
|
||||
''"${v}"''
|
||||
else if builtins.isList v then
|
||||
"(${lib.concatStringsSep " " (map toZshValue v)})"
|
||||
else
|
||||
''"${toString v}"'';
|
||||
|
||||
# Produces a Zsh shell like definition statement
|
||||
define = n: v: "${n}=${toZshValue v}";
|
||||
|
||||
# Given an attribute set containing shell variable names and their
|
||||
# assignments, this function produces a string containing a definition
|
||||
# statement for each set entry.
|
||||
defineAll = vars: lib.concatStringsSep "\n" (lib.mapAttrsToList define vars);
|
||||
|
||||
# Produces a Zsh shell like export statement
|
||||
export = n: v: "export ${define n v}";
|
||||
|
||||
# Given an attribute set containing shell variable names and their
|
||||
# assignments, this function produces a string containing an export
|
||||
# statement for each set entry.
|
||||
exportAll = vars: lib.concatStringsSep "\n" (lib.mapAttrsToList export vars);
|
||||
}
|
||||
@@ -1,49 +1,27 @@
|
||||
{ config, lib, pkgs, baseModules, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
/* For the purpose of generating docs, evaluate options with each derivation
|
||||
in `pkgs` (recursively) replaced by a fake with path "\${pkgs.attribute.path}".
|
||||
It isn't perfect, but it seems to cover a vast majority of use cases.
|
||||
Caveat: even if the package is reached by a different means,
|
||||
the path above will be shown and not e.g. `${config.services.foo.package}`. */
|
||||
nixosManual = import <nixpkgs/nixos/doc/manual> {
|
||||
inherit pkgs config;
|
||||
version = "0.1";
|
||||
revision = "release-0.1";
|
||||
options =
|
||||
let
|
||||
scrubbedEval = evalModules {
|
||||
modules = [ { nixpkgs.system = pkgs.stdenv.system; } ] ++ baseModules;
|
||||
args = (config._module.args) // { modules = [ ]; };
|
||||
specialArgs = { pkgs = scrubDerivations "pkgs" pkgs; };
|
||||
};
|
||||
scrubDerivations = namePrefix: pkgSet: mapAttrs
|
||||
(name: value:
|
||||
let wholeName = "${namePrefix}.${name}"; in
|
||||
if isAttrs value then
|
||||
scrubDerivations wholeName value
|
||||
// (optionalAttrs (isDerivation value) { outPath = "\${${wholeName}}"; })
|
||||
else value
|
||||
)
|
||||
pkgSet;
|
||||
in scrubbedEval.options;
|
||||
};
|
||||
cfg = config.manual;
|
||||
|
||||
homeEnvironmentManPages = pkgs.runCommand "home-environment-manpages" {
|
||||
allowedReferences = [ "out" ];
|
||||
} ''
|
||||
install -v -D -m444 \
|
||||
${nixosManual.manpages}/share/man/man5/configuration.nix.5 \
|
||||
$out/share/man/man5/home-configuration.nix.5
|
||||
'';
|
||||
docs = import ../doc { inherit lib pkgs; };
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
options = {
|
||||
manual.html.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to install the HTML manual. This also installs the
|
||||
<command>home-manager-help</command> tool, which opens a local
|
||||
copy of the Home Manager manual in the system web browser.
|
||||
'';
|
||||
};
|
||||
|
||||
manual.manpages.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
@@ -57,12 +35,34 @@ in
|
||||
Thanks!
|
||||
'';
|
||||
};
|
||||
|
||||
manual.json.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
example = true;
|
||||
description = ''
|
||||
Whether to install a JSON formatted list of all Home Manager
|
||||
options. This can be located at
|
||||
<filename><profile directory>/share/doc/home-manager/options.json</filename>,
|
||||
and may be used for navigating definitions, auto-completing,
|
||||
and other miscellaneous tasks.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf config.manual.manpages.enable {
|
||||
# To fix error during manpage build.
|
||||
meta.doc = builtins.toFile "nothingness" "<para></para>";
|
||||
config = {
|
||||
home.packages = mkMerge [
|
||||
(mkIf cfg.html.enable [ docs.manual.html docs.manual.htmlOpenTool ])
|
||||
(mkIf cfg.manpages.enable [ docs.manPages ])
|
||||
(mkIf cfg.json.enable [ docs.options.json ])
|
||||
];
|
||||
|
||||
home.packages = [ homeEnvironmentManPages ];
|
||||
# Whether a dependency on nmd should be introduced.
|
||||
home.extraBuilderCommands =
|
||||
mkIf (cfg.html.enable || cfg.manpages.enable || cfg.json.enable) ''
|
||||
mkdir $out/lib
|
||||
ln -s ${docs.nmdSrc} $out/lib/nmd
|
||||
'';
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
70
modules/misc/dconf.nix
Normal file
70
modules/misc/dconf.nix
Normal file
@@ -0,0 +1,70 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.dconf;
|
||||
|
||||
toDconfIni = generators.toINI { mkKeyValue = mkIniKeyValue; };
|
||||
|
||||
mkIniKeyValue = key: value: "${key}=${toString (hm.gvariant.mkValue value)}";
|
||||
|
||||
in {
|
||||
meta.maintainers = [ maintainers.gnidorah maintainers.rycee ];
|
||||
|
||||
options = {
|
||||
dconf = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
visible = false;
|
||||
description = ''
|
||||
Whether to enable dconf settings.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = with types; attrsOf (attrsOf hm.types.gvariant);
|
||||
default = { };
|
||||
example = literalExample ''
|
||||
{
|
||||
"org/gnome/calculator" = {
|
||||
button-mode = "programming";
|
||||
show-thousands = true;
|
||||
base = 10;
|
||||
word-size = 64;
|
||||
window-position = lib.hm.gvariant.mkTuple [100 100];
|
||||
};
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
Settings to write to the dconf configuration system.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf (cfg.enable && cfg.settings != { }) {
|
||||
# Make sure the dconf directory exists.
|
||||
xdg.configFile."dconf/.keep".source = builtins.toFile "keep" "";
|
||||
|
||||
home.activation.dconfSettings = hm.dag.entryAfter [ "installPackages" ]
|
||||
(let iniFile = pkgs.writeText "hm-dconf.ini" (toDconfIni cfg.settings);
|
||||
in ''
|
||||
if [[ -v DBUS_SESSION_BUS_ADDRESS ]]; then
|
||||
DCONF_DBUS_RUN_SESSION=""
|
||||
else
|
||||
DCONF_DBUS_RUN_SESSION="${pkgs.dbus}/bin/dbus-run-session"
|
||||
fi
|
||||
|
||||
if [[ -v DRY_RUN ]]; then
|
||||
echo $DCONF_DBUS_RUN_SESSION ${pkgs.dconf}/bin/dconf load / "<" ${iniFile}
|
||||
else
|
||||
$DCONF_DBUS_RUN_SESSION ${pkgs.dconf}/bin/dconf load / < ${iniFile}
|
||||
fi
|
||||
|
||||
unset DCONF_DBUS_RUN_SESSION
|
||||
'');
|
||||
};
|
||||
}
|
||||
26
modules/misc/debug.nix
Normal file
26
modules/misc/debug.nix
Normal file
@@ -0,0 +1,26 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
options.home = {
|
||||
enableDebugInfo = mkEnableOption "" // {
|
||||
description = ''
|
||||
Some Nix-packages provide debug symbols for
|
||||
<command>gdb</command> in the <literal>debug</literal>-output.
|
||||
This option ensures that those are automatically fetched from
|
||||
the binary cache if available and <command>gdb</command> is
|
||||
configured to find those symbols.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf config.home.enableDebugInfo {
|
||||
home.extraOutputsToInstall = [ "debug" ];
|
||||
|
||||
home.sessionVariables = {
|
||||
NIX_DEBUG_INFO_DIRS =
|
||||
"$NIX_DEBUG_INFO_DIRS\${NIX_DEBUG_INFO_DIRS:+:}${config.home.profileDirectory}/lib/debug";
|
||||
};
|
||||
};
|
||||
}
|
||||
105
modules/misc/fontconfig.nix
Normal file
105
modules/misc/fontconfig.nix
Normal file
@@ -0,0 +1,105 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.fonts.fontconfig;
|
||||
|
||||
profileDirectory = config.home.profileDirectory;
|
||||
|
||||
in {
|
||||
meta.maintainers = [ maintainers.rycee ];
|
||||
|
||||
imports = [
|
||||
(mkRenamedOptionModule [ "fonts" "fontconfig" "enableProfileFonts" ] [
|
||||
"fonts"
|
||||
"fontconfig"
|
||||
"enable"
|
||||
])
|
||||
];
|
||||
|
||||
options = {
|
||||
fonts.fontconfig = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable fontconfig configuration. This will, for
|
||||
example, allow fontconfig to discover fonts and
|
||||
configurations installed through
|
||||
<varname>home.packages</varname> and
|
||||
<command>nix-env</command>.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Create two dummy files in /lib/fontconfig to make sure that
|
||||
# buildEnv creates a real directory path. These files are removed
|
||||
# in home.extraProfileCommands below so the packages will not
|
||||
# become "runtime" dependencies.
|
||||
home.packages = [
|
||||
(pkgs.writeTextFile {
|
||||
name = "hm-dummy1";
|
||||
destination = "/lib/fontconfig/hm-dummy1";
|
||||
text = "dummy";
|
||||
})
|
||||
|
||||
(pkgs.writeTextFile {
|
||||
name = "hm-dummy2";
|
||||
destination = "/lib/fontconfig/hm-dummy2";
|
||||
text = "dummy";
|
||||
})
|
||||
];
|
||||
|
||||
home.extraProfileCommands = ''
|
||||
if [[ -d $out/lib/X11/fonts || -d $out/share/fonts ]]; then
|
||||
export FONTCONFIG_FILE="$(pwd)/fonts.conf"
|
||||
|
||||
cat > $FONTCONFIG_FILE << EOF
|
||||
<?xml version='1.0'?>
|
||||
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
|
||||
<fontconfig>
|
||||
<dir>$out/lib/X11/fonts</dir>
|
||||
<dir>$out/share/fonts</dir>
|
||||
<cachedir>$out/lib/fontconfig/cache</cachedir>
|
||||
</fontconfig>
|
||||
EOF
|
||||
|
||||
${getBin pkgs.fontconfig}/bin/fc-cache -f
|
||||
rm -f $out/lib/fontconfig/cache/CACHEDIR.TAG
|
||||
rmdir --ignore-fail-on-non-empty -p $out/lib/fontconfig/cache
|
||||
|
||||
rm "$FONTCONFIG_FILE"
|
||||
unset FONTCONFIG_FILE
|
||||
fi
|
||||
|
||||
# Remove hacky dummy files.
|
||||
rm $out/lib/fontconfig/hm-dummy?
|
||||
rmdir --ignore-fail-on-non-empty -p $out/lib/fontconfig
|
||||
'';
|
||||
|
||||
xdg.configFile = {
|
||||
"fontconfig/conf.d/10-hm-fonts.conf".text = ''
|
||||
<?xml version='1.0'?>
|
||||
|
||||
<!-- Generated by Home Manager. -->
|
||||
|
||||
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
|
||||
<fontconfig>
|
||||
<include ignore_missing="yes">${config.home.path}/etc/fonts/conf.d</include>
|
||||
<include ignore_missing="yes">${config.home.path}/etc/fonts/fonts.conf</include>
|
||||
|
||||
<dir>${config.home.path}/lib/X11/fonts</dir>
|
||||
<dir>${config.home.path}/share/fonts</dir>
|
||||
<dir>${profileDirectory}/lib/X11/fonts</dir>
|
||||
<dir>${profileDirectory}/share/fonts</dir>
|
||||
|
||||
<cachedir>${config.home.path}/lib/fontconfig/cache</cachedir>
|
||||
</fontconfig>
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -8,124 +8,161 @@ let
|
||||
cfg2 = config.gtk.gtk2;
|
||||
cfg3 = config.gtk.gtk3;
|
||||
|
||||
toGtk3Ini = (import ../lib/generators.nix).toINI {
|
||||
toGtk3Ini = generators.toINI {
|
||||
mkKeyValue = key: value:
|
||||
let
|
||||
value' =
|
||||
if isBool value then (if value then "true" else "false")
|
||||
else toString value;
|
||||
in
|
||||
"${key}=${value'}";
|
||||
value' = if isBool value then
|
||||
(if value then "true" else "false")
|
||||
else
|
||||
toString value;
|
||||
in "${key}=${value'}";
|
||||
};
|
||||
|
||||
formatGtk2Option = n: v:
|
||||
let
|
||||
v' =
|
||||
if isBool v then (if v then "true" else "false")
|
||||
else if isString v then "\"${v}\""
|
||||
else toString v;
|
||||
in
|
||||
"${n} = ${v'}";
|
||||
v' = if isBool v then
|
||||
(if v then "true" else "false")
|
||||
else if isString v then
|
||||
''"${v}"''
|
||||
else
|
||||
toString v;
|
||||
in "${n} = ${v'}";
|
||||
|
||||
in
|
||||
themeType = types.submodule {
|
||||
options = {
|
||||
package = mkOption {
|
||||
type = types.nullOr types.package;
|
||||
default = null;
|
||||
example = literalExample "pkgs.gnome3.gnome_themes_standard";
|
||||
description = ''
|
||||
Package providing the theme. This package will be installed
|
||||
to your profile. If <literal>null</literal> then the theme
|
||||
is assumed to already be available in your profile.
|
||||
'';
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
example = "Adwaita";
|
||||
description = "The name of the theme within the package.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
in {
|
||||
meta.maintainers = [ maintainers.rycee ];
|
||||
|
||||
imports = [
|
||||
(mkRemovedOptionModule [ "gtk" "gtk3" "waylandSupport" ] ''
|
||||
This options is not longer needed and can be removed.
|
||||
'')
|
||||
];
|
||||
|
||||
{
|
||||
options = {
|
||||
gtk = {
|
||||
enable = mkEnableOption "GTK 2/3 configuration";
|
||||
|
||||
fontName = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
font = mkOption {
|
||||
type = types.nullOr hm.types.fontType;
|
||||
default = null;
|
||||
example = "DejaVu Sans 8";
|
||||
description = ''
|
||||
The font to use in GTK+ 2/3 applications.
|
||||
'';
|
||||
};
|
||||
|
||||
themeName = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
iconTheme = mkOption {
|
||||
type = types.nullOr themeType;
|
||||
default = null;
|
||||
example = "Vertex-Dark";
|
||||
description = "The name of the GTK+2/3 theme to use.";
|
||||
description = "The icon theme to use.";
|
||||
};
|
||||
|
||||
iconThemeName = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
theme = mkOption {
|
||||
type = types.nullOr themeType;
|
||||
default = null;
|
||||
example = "Tango";
|
||||
description = "The name of the icon theme to use.";
|
||||
description = "The GTK+2/3 theme to use.";
|
||||
};
|
||||
|
||||
gtk2 = mkOption {
|
||||
description = "Options specific to GTK+ 2";
|
||||
default = {};
|
||||
type = types.submodule {
|
||||
options = {
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = "gtk-can-change-accels = 1";
|
||||
description = ''
|
||||
Extra configuration lines to add verbatim to
|
||||
<filename>~/.gtkrc-2.0</filename>.
|
||||
'';
|
||||
};
|
||||
};
|
||||
gtk2 = {
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = "gtk-can-change-accels = 1";
|
||||
description = ''
|
||||
Extra configuration lines to add verbatim to
|
||||
<filename>~/.gtkrc-2.0</filename>.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
gtk3 = mkOption {
|
||||
description = "Options specific to GTK+ 3";
|
||||
default = {};
|
||||
type = types.submodule {
|
||||
options = {
|
||||
extraConfig = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
example = { gtk-cursor-blink = false; gtk-recent-files-limit = 20; };
|
||||
description = ''
|
||||
Extra configuration options to add to
|
||||
<filename>~/.config/gtk-3.0/settings.ini</filename>.
|
||||
'';
|
||||
};
|
||||
gtk3 = {
|
||||
bookmarks = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
example = [ "file:///home/jane/Documents" ];
|
||||
description = "Bookmarks in the sidebar of the GTK file browser";
|
||||
};
|
||||
|
||||
extraCss = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Extra configuration lines to add verbatim to
|
||||
<filename>~/.config/gtk-3.0/gtk.css</filename>.
|
||||
'';
|
||||
};
|
||||
extraConfig = mkOption {
|
||||
type = with types; attrsOf (either bool (either int str));
|
||||
default = { };
|
||||
example = {
|
||||
gtk-cursor-blink = false;
|
||||
gtk-recent-files-limit = 20;
|
||||
};
|
||||
description = ''
|
||||
Extra configuration options to add to
|
||||
<filename>~/.config/gtk-3.0/settings.ini</filename>.
|
||||
'';
|
||||
};
|
||||
|
||||
extraCss = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Extra configuration lines to add verbatim to
|
||||
<filename>~/.config/gtk-3.0/gtk.css</filename>.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable (
|
||||
let
|
||||
ini =
|
||||
optionalAttrs (cfg.fontName != null)
|
||||
{ gtk-font-name = cfg.fontName; }
|
||||
//
|
||||
optionalAttrs (cfg.themeName != null)
|
||||
{ gtk-theme-name = cfg.themeName; }
|
||||
//
|
||||
optionalAttrs (cfg.iconThemeName != null)
|
||||
{ gtk-icon-theme-name = cfg.iconThemeName; };
|
||||
in
|
||||
{
|
||||
home.file.".gtkrc-2.0".text =
|
||||
concatStringsSep "\n" (
|
||||
mapAttrsToList formatGtk2Option ini
|
||||
) + "\n" + cfg2.extraConfig;
|
||||
config = mkIf cfg.enable (let
|
||||
ini = optionalAttrs (cfg.font != null) {
|
||||
gtk-font-name = let
|
||||
fontSize =
|
||||
optionalString (cfg.font.size != null) " ${toString cfg.font.size}";
|
||||
in "${cfg.font.name}" + fontSize;
|
||||
} // optionalAttrs (cfg.theme != null) { gtk-theme-name = cfg.theme.name; }
|
||||
// optionalAttrs (cfg.iconTheme != null) {
|
||||
gtk-icon-theme-name = cfg.iconTheme.name;
|
||||
};
|
||||
|
||||
home.file.".config/gtk-3.0/settings.ini".text =
|
||||
toGtk3Ini { Settings = ini // cfg3.extraConfig; };
|
||||
dconfIni = optionalAttrs (cfg.font != null) { font-name = cfg.font.name; }
|
||||
// optionalAttrs (cfg.theme != null) { gtk-theme = cfg.theme.name; }
|
||||
// optionalAttrs (cfg.iconTheme != null) {
|
||||
icon-theme = cfg.iconTheme.name;
|
||||
};
|
||||
|
||||
home.file.".config/gtk-3.0/gtk.css".text = cfg3.extraCss;
|
||||
}
|
||||
);
|
||||
optionalPackage = opt:
|
||||
optional (opt != null && opt.package != null) opt.package;
|
||||
in {
|
||||
home.packages = optionalPackage cfg.font ++ optionalPackage cfg.theme
|
||||
++ optionalPackage cfg.iconTheme;
|
||||
|
||||
home.file.".gtkrc-2.0".text =
|
||||
concatStringsSep "\n" (mapAttrsToList formatGtk2Option ini) + "\n"
|
||||
+ cfg2.extraConfig;
|
||||
|
||||
xdg.configFile."gtk-3.0/settings.ini".text =
|
||||
toGtk3Ini { Settings = ini // cfg3.extraConfig; };
|
||||
|
||||
xdg.configFile."gtk-3.0/gtk.css".text = cfg3.extraCss;
|
||||
|
||||
xdg.configFile."gtk-3.0/bookmarks" = mkIf (cfg3.bookmarks != [ ]) {
|
||||
text = concatStringsSep "\n" cfg3.bookmarks;
|
||||
};
|
||||
|
||||
dconf.settings."org/gnome/desktop/interface" = dconfIni;
|
||||
});
|
||||
}
|
||||
|
||||
14
modules/misc/lib.nix
Normal file
14
modules/misc/lib.nix
Normal file
@@ -0,0 +1,14 @@
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
options = {
|
||||
lib = lib.mkOption {
|
||||
type = lib.types.attrsOf lib.types.attrs;
|
||||
default = { };
|
||||
description = ''
|
||||
This option allows modules to define helper functions,
|
||||
constants, etc.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
1892
modules/misc/news.nix
Normal file
1892
modules/misc/news.nix
Normal file
File diff suppressed because it is too large
Load Diff
152
modules/misc/nixpkgs.nix
Normal file
152
modules/misc/nixpkgs.nix
Normal file
@@ -0,0 +1,152 @@
|
||||
# Adapted from Nixpkgs.
|
||||
|
||||
{ config, lib, pkgs, pkgsPath, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
isConfig = x:
|
||||
builtins.isAttrs x || builtins.isFunction x;
|
||||
|
||||
optCall = f: x:
|
||||
if builtins.isFunction f
|
||||
then f x
|
||||
else f;
|
||||
|
||||
mergeConfig = lhs_: rhs_:
|
||||
let
|
||||
lhs = optCall lhs_ { inherit pkgs; };
|
||||
rhs = optCall rhs_ { inherit pkgs; };
|
||||
in
|
||||
lhs // rhs //
|
||||
optionalAttrs (lhs ? packageOverrides) {
|
||||
packageOverrides = pkgs:
|
||||
optCall lhs.packageOverrides pkgs //
|
||||
optCall (attrByPath ["packageOverrides"] ({}) rhs) pkgs;
|
||||
} //
|
||||
optionalAttrs (lhs ? perlPackageOverrides) {
|
||||
perlPackageOverrides = pkgs:
|
||||
optCall lhs.perlPackageOverrides pkgs //
|
||||
optCall (attrByPath ["perlPackageOverrides"] ({}) rhs) pkgs;
|
||||
};
|
||||
|
||||
configType = mkOptionType {
|
||||
name = "nixpkgs-config";
|
||||
description = "nixpkgs config";
|
||||
check = x:
|
||||
let traceXIfNot = c:
|
||||
if c x then true
|
||||
else lib.traceSeqN 1 x false;
|
||||
in traceXIfNot isConfig;
|
||||
merge = args: fold (def: mergeConfig def.value) {};
|
||||
};
|
||||
|
||||
overlayType = mkOptionType {
|
||||
name = "nixpkgs-overlay";
|
||||
description = "nixpkgs overlay";
|
||||
check = builtins.isFunction;
|
||||
merge = lib.mergeOneOption;
|
||||
};
|
||||
|
||||
_pkgs = import pkgsPath (
|
||||
filterAttrs (n: v: v != null) config.nixpkgs
|
||||
);
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
options.nixpkgs = {
|
||||
config = mkOption {
|
||||
default = null;
|
||||
example = { allowBroken = true; };
|
||||
type = types.nullOr configType;
|
||||
description = ''
|
||||
The configuration of the Nix Packages collection. (For
|
||||
details, see the Nixpkgs documentation.) It allows you to set
|
||||
package configuration options.
|
||||
|
||||
</para><para>
|
||||
|
||||
If <literal>null</literal>, then configuration is taken from
|
||||
the fallback location, for example,
|
||||
<filename>~/.config/nixpkgs/config.nix</filename>.
|
||||
|
||||
</para><para>
|
||||
|
||||
Note, this option will not apply outside your Home Manager
|
||||
configuration like when installing manually through
|
||||
<command>nix-env</command>. If you want to apply it both
|
||||
inside and outside Home Manager you can put it in a separate
|
||||
file and include something like
|
||||
|
||||
<programlisting language="nix">
|
||||
nixpkgs.config = import ./nixpkgs-config.nix;
|
||||
xdg.configFile."nixpkgs/config.nix".source = ./nixpkgs-config.nix;
|
||||
</programlisting>
|
||||
|
||||
in your Home Manager configuration.
|
||||
'';
|
||||
};
|
||||
|
||||
overlays = mkOption {
|
||||
default = null;
|
||||
example = literalExample
|
||||
''
|
||||
[ (self: super: {
|
||||
openssh = super.openssh.override {
|
||||
hpnSupport = true;
|
||||
withKerberos = true;
|
||||
kerberos = self.libkrb5;
|
||||
};
|
||||
};
|
||||
) ]
|
||||
'';
|
||||
type = types.nullOr (types.listOf overlayType);
|
||||
description = ''
|
||||
List of overlays to use with the Nix Packages collection. (For
|
||||
details, see the Nixpkgs documentation.) It allows you to
|
||||
override packages globally. This is a function that takes as
|
||||
an argument the <emphasis>original</emphasis> Nixpkgs. The
|
||||
first argument should be used for finding dependencies, and
|
||||
the second should be used for overriding recipes.
|
||||
|
||||
</para><para>
|
||||
|
||||
If <literal>null</literal>, then the overlays are taken from
|
||||
the fallback location, for example,
|
||||
<filename>~/.config/nixpkgs/overlays</filename>.
|
||||
|
||||
</para><para>
|
||||
|
||||
Like <varname>nixpkgs.config</varname> this option only
|
||||
applies within the Home Manager configuration. See
|
||||
<varname>nixpkgs.config</varname> for a suggested setup that
|
||||
works both internally and externally.
|
||||
'';
|
||||
};
|
||||
|
||||
system = mkOption {
|
||||
type = types.str;
|
||||
example = "i686-linux";
|
||||
internal = true;
|
||||
description = ''
|
||||
Specifies the Nix platform type for which the user environment
|
||||
should be built. If unset, it defaults to the platform type of
|
||||
your host system. Specifying this option is useful when doing
|
||||
distributed multi-platform deployment, or when building
|
||||
virtual machines.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
_module.args = {
|
||||
pkgs = mkOverride modules.defaultPriority _pkgs;
|
||||
pkgs_i686 =
|
||||
if _pkgs.stdenv.isLinux && _pkgs.stdenv.hostPlatform.isx86
|
||||
then _pkgs.pkgsi686Linux
|
||||
else { };
|
||||
};
|
||||
};
|
||||
}
|
||||
31
modules/misc/numlock.nix
Normal file
31
modules/misc/numlock.nix
Normal file
@@ -0,0 +1,31 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.xsession.numlock;
|
||||
|
||||
in {
|
||||
meta.maintainers = [ maintainers.evanjs ];
|
||||
|
||||
options = { xsession.numlock.enable = mkEnableOption "Num Lock"; };
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.user.services.numlockx = {
|
||||
Unit = {
|
||||
Description = "NumLockX";
|
||||
After = [ "graphical-session-pre.target" ];
|
||||
PartOf = [ "graphical-session.target" ];
|
||||
};
|
||||
|
||||
Service = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecStart = "${pkgs.numlockx}/bin/numlockx";
|
||||
};
|
||||
|
||||
Install = { WantedBy = [ "graphical-session.target" ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -4,17 +4,32 @@ with lib;
|
||||
|
||||
let
|
||||
|
||||
homeCfg = config.home;
|
||||
vars = config.pam.sessionVariables;
|
||||
|
||||
in
|
||||
in {
|
||||
meta.maintainers = [ maintainers.rycee ];
|
||||
|
||||
{
|
||||
options = {};
|
||||
options = {
|
||||
pam.sessionVariables = mkOption {
|
||||
default = { };
|
||||
type = types.attrs;
|
||||
example = { EDITOR = "vim"; };
|
||||
description = ''
|
||||
Environment variables that will be set for the PAM session.
|
||||
The variable values must be as described in
|
||||
<citerefentry>
|
||||
<refentrytitle>pam_env.conf</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</citerefentry>.
|
||||
</para><para>
|
||||
Note, this option will become deprecated in the future and its use is
|
||||
therefore discouraged.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf (homeCfg.sessionVariableSetter == "pam") {
|
||||
home.file.".pam_environment".text =
|
||||
concatStringsSep "\n" (
|
||||
mapAttrsToList (n: v: "${n} OVERRIDE=${v}") homeCfg.sessionVariables
|
||||
) + "\n";
|
||||
config = mkIf (vars != { }) {
|
||||
home.file.".pam_environment".text = concatStringsSep "\n"
|
||||
(mapAttrsToList (n: v: ''${n} OVERRIDE="${toString v}"'') vars) + "\n";
|
||||
};
|
||||
}
|
||||
|
||||
121
modules/misc/qt.nix
Normal file
121
modules/misc/qt.nix
Normal file
@@ -0,0 +1,121 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.qt;
|
||||
|
||||
in {
|
||||
meta.maintainers = [ maintainers.rycee ];
|
||||
|
||||
imports = [
|
||||
(mkChangedOptionModule [ "qt" "useGtkTheme" ] [ "qt" "platformTheme" ]
|
||||
(config:
|
||||
if getAttrFromPath [ "qt" "useGtkTheme" ] config then "gtk" else null))
|
||||
];
|
||||
|
||||
options = {
|
||||
qt = {
|
||||
enable = mkEnableOption "Qt 4 and 5 configuration";
|
||||
|
||||
platformTheme = mkOption {
|
||||
type = types.nullOr (types.enum [ "gtk" "gnome" ]);
|
||||
default = null;
|
||||
example = "gnome";
|
||||
relatedPackages =
|
||||
[ "qgnomeplatform" [ "libsForQt5" "qtstyleplugins" ] ];
|
||||
description = ''
|
||||
Selects the platform theme to use for Qt applications.</para>
|
||||
<para>The options are
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><literal>gtk</literal></term>
|
||||
<listitem><para>Use GTK theme with
|
||||
<link xlink:href="https://github.com/qt/qtstyleplugins">qtstyleplugins</link>
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><literal>gnome</literal></term>
|
||||
<listitem><para>Use GNOME theme with
|
||||
<link xlink:href="https://github.com/FedoraQt/QGnomePlatform">qgnomeplatform</link>
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
'';
|
||||
};
|
||||
|
||||
style = {
|
||||
name = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "adwaita-dark";
|
||||
relatedPackages = [ "adwaita-qt" [ "libsForQt5" "qtstyleplugins" ] ];
|
||||
description = ''
|
||||
Selects the style to use for Qt5 applications.</para>
|
||||
<para>The options are
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><literal>adwaita</literal></term>
|
||||
<term><literal>adwaita-dark</literal></term>
|
||||
<listitem><para>Use Adwaita Qt style with
|
||||
<link xlink:href="https://github.com/FedoraQt/adwaita-qt">adwaita</link>
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><literal>cleanlooks</literal></term>
|
||||
<term><literal>gtk2</literal></term>
|
||||
<term><literal>motif</literal></term>
|
||||
<term><literal>plastique</literal></term>
|
||||
<listitem><para>Use styles from
|
||||
<link xlink:href="https://github.com/qt/qtstyleplugins">qtstyleplugins</link>
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = types.nullOr types.package;
|
||||
default = null;
|
||||
example = literalExample "pkgs.adwaita-qt";
|
||||
description = "Theme package to be used in Qt5 applications.";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf (cfg.enable && cfg.platformTheme != null) {
|
||||
assertions = [{
|
||||
assertion = (cfg.platformTheme == "gnome")
|
||||
-> ((cfg.style.name != null) && (cfg.style.package != null));
|
||||
message = ''
|
||||
`qt.platformTheme` "gnome" must have `qt.style` set to a theme that
|
||||
supports both Qt and Gtk, for example "adwaita" or "adwaita-dark".
|
||||
'';
|
||||
}];
|
||||
|
||||
# Necessary because home.sessionVariables is of types.attrs
|
||||
home.sessionVariables = (filterAttrs (n: v: v != null) {
|
||||
QT_QPA_PLATFORMTHEME =
|
||||
if cfg.platformTheme == "gnome" then "gnome" else "gtk2";
|
||||
QT_STYLE_OVERRIDE = cfg.style.name;
|
||||
});
|
||||
|
||||
home.packages = if cfg.platformTheme == "gnome" then
|
||||
[ pkgs.qgnomeplatform ]
|
||||
++ lib.optionals (cfg.style.package != null) [ cfg.style.package ]
|
||||
else
|
||||
[ pkgs.libsForQt5.qtstyleplugins ];
|
||||
|
||||
xsession.importedVariables = [ "QT_QPA_PLATFORMTHEME" ]
|
||||
++ lib.optionals (cfg.style != null) [ "QT_STYLE_OVERRIDE" ];
|
||||
|
||||
# Enable GTK+ style for Qt4 in either case.
|
||||
# It doesn’t support the platform theme packages.
|
||||
home.activation.useGtkThemeInQt4 = hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||
$DRY_RUN_CMD ${pkgs.crudini}/bin/crudini $VERBOSE_ARG \
|
||||
--set "${config.xdg.configHome}/Trolltech.conf" Qt style GTK+
|
||||
'';
|
||||
};
|
||||
}
|
||||
32
modules/misc/submodule-support.nix
Normal file
32
modules/misc/submodule-support.nix
Normal file
@@ -0,0 +1,32 @@
|
||||
{ lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
meta.maintainers = [ maintainers.rycee ];
|
||||
|
||||
options.submoduleSupport = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
internal = true;
|
||||
description = ''
|
||||
Whether the Home Manager module system is used as a submodule
|
||||
in, for example, NixOS or nix-darwin.
|
||||
'';
|
||||
};
|
||||
|
||||
externalPackageInstall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
internal = true;
|
||||
description = ''
|
||||
Whether the packages of <option>home.packages</option> are
|
||||
installed separately from the Home Manager activation script.
|
||||
In NixOS, for example, this may be accomplished by installing
|
||||
the packages through
|
||||
<option>users.users.‹name?›.packages</option>.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
49
modules/misc/tmpfiles.nix
Normal file
49
modules/misc/tmpfiles.nix
Normal file
@@ -0,0 +1,49 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.systemd.user.tmpfiles;
|
||||
|
||||
in {
|
||||
meta.maintainers = [ maintainers.dawidsowa ];
|
||||
|
||||
options.systemd.user.tmpfiles.rules = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
example = [ "L /home/user/Documents - - - - /mnt/data/Documents" ];
|
||||
description = ''
|
||||
Rules for creating and cleaning up temporary files
|
||||
automatically. See
|
||||
<citerefentry>
|
||||
<refentrytitle>tmpfiles.d</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</citerefentry>
|
||||
for the exact format.
|
||||
'';
|
||||
};
|
||||
|
||||
config = mkIf (cfg.rules != [ ]) {
|
||||
xdg = {
|
||||
dataFile."user-tmpfiles.d/home-manager.conf" = {
|
||||
text = ''
|
||||
# This file is created automatically and should not be modified.
|
||||
# Please change the option ‘systemd.user.tmpfiles.rules’ instead.
|
||||
${concatStringsSep "\n" cfg.rules}
|
||||
'';
|
||||
onChange = "${pkgs.systemd}/bin/systemd-tmpfiles --user --create";
|
||||
};
|
||||
configFile = {
|
||||
"systemd/user/basic.target.wants/systemd-tmpfiles-setup.service".source =
|
||||
"${pkgs.systemd}/example/systemd/user/systemd-tmpfiles-setup.service";
|
||||
"systemd/user/systemd-tmpfiles-setup.service".source =
|
||||
"${pkgs.systemd}/example/systemd/user/systemd-tmpfiles-setup.service";
|
||||
"systemd/user/timers.target.wants/systemd-tmpfiles-clean.timer".source =
|
||||
"${pkgs.systemd}/example/systemd/user/systemd-tmpfiles-clean.timer";
|
||||
"systemd/user/systemd-tmpfiles-clean.service".source =
|
||||
"${pkgs.systemd}/example/systemd/user/systemd-tmpfiles-clean.service";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
25
modules/misc/version.nix
Normal file
25
modules/misc/version.nix
Normal file
@@ -0,0 +1,25 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
options = {
|
||||
home.stateVersion = mkOption {
|
||||
type =
|
||||
types.enum [ "18.09" "19.03" "19.09" "20.03" "20.09" "21.03" "21.05" ];
|
||||
default = "18.09";
|
||||
description = ''
|
||||
It is occasionally necessary for Home Manager to change
|
||||
configuration defaults in a way that is incompatible with
|
||||
stateful data. This could, for example, include switching the
|
||||
default data format or location of a file.
|
||||
</para><para>
|
||||
The <emphasis>state version</emphasis> indicates which default
|
||||
settings are in effect and will therefore help avoid breaking
|
||||
program configurations. Switching to a higher state version
|
||||
typically requires performing some manual steps, such as data
|
||||
conversion or moving files.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
51
modules/misc/vte.nix
Normal file
51
modules/misc/vte.nix
Normal file
@@ -0,0 +1,51 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
meta.maintainers = [ maintainers.rycee ];
|
||||
|
||||
options.programs = let
|
||||
description = ''
|
||||
Whether to enable integration with terminals using the VTE
|
||||
library. This will let the terminal track the current working
|
||||
directory.
|
||||
'';
|
||||
in {
|
||||
bash.enableVteIntegration = mkEnableOption "" // { inherit description; };
|
||||
|
||||
zsh.enableVteIntegration = mkEnableOption "" // { inherit description; };
|
||||
};
|
||||
|
||||
config = mkMerge [
|
||||
(mkIf config.programs.bash.enableVteIntegration {
|
||||
# Unfortunately we have to do a little dance here to fix two
|
||||
# problems with the upstream vte.sh file:
|
||||
#
|
||||
# - It does `PROMPT_COMMAND="__vte_prompt_command"` which
|
||||
# clobbers any previously assigned prompt command.
|
||||
#
|
||||
# - Its `__vte_prompt_command` function runs commands that will
|
||||
# overwrite the exit status of the command the user ran.
|
||||
programs.bash.initExtra = ''
|
||||
__HM_PROMPT_COMMAND="''${PROMPT_COMMAND:+''${PROMPT_COMMAND%;};}__hm_vte_prompt_command"
|
||||
. ${pkgs.vte}/etc/profile.d/vte.sh
|
||||
if [[ $(type -t __vte_prompt_command) = function ]]; then
|
||||
__hm_vte_prompt_command() {
|
||||
local old_exit_status=$?
|
||||
__vte_prompt_command
|
||||
return $old_exit_status
|
||||
}
|
||||
PROMPT_COMMAND="$__HM_PROMPT_COMMAND"
|
||||
fi
|
||||
unset __HM_PROMPT_COMMAND
|
||||
'';
|
||||
})
|
||||
|
||||
(mkIf config.programs.zsh.enableVteIntegration {
|
||||
programs.zsh.initExtra = ''
|
||||
. ${pkgs.vte}/etc/profile.d/vte.sh
|
||||
'';
|
||||
})
|
||||
];
|
||||
}
|
||||
88
modules/misc/xdg-mime-apps.nix
Normal file
88
modules/misc/xdg-mime-apps.nix
Normal file
@@ -0,0 +1,88 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.xdg.mimeApps;
|
||||
|
||||
strListOrSingleton = with types;
|
||||
coercedTo (either (listOf str) str) toList (listOf str);
|
||||
|
||||
in {
|
||||
meta.maintainers = with maintainers; [ pacien ];
|
||||
|
||||
options.xdg.mimeApps = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to manage <filename>$XDG_CONFIG_HOME/mimeapps.list</filename>.
|
||||
</para>
|
||||
<para>
|
||||
The generated file is read-only.
|
||||
'';
|
||||
};
|
||||
|
||||
# descriptions from
|
||||
# https://specifications.freedesktop.org/mime-apps-spec/mime-apps-spec-1.0.1.html
|
||||
|
||||
associations.added = mkOption {
|
||||
type = types.attrsOf strListOrSingleton;
|
||||
default = { };
|
||||
example = literalExample ''
|
||||
{
|
||||
"mimetype1" = [ "foo1.desktop" "foo2.desktop" "foo3.desktop" ];
|
||||
"mimetype2" = "foo4.desktop";
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
Defines additional associations of applications with
|
||||
mimetypes, as if the .desktop file was listing this mimetype
|
||||
in the first place.
|
||||
'';
|
||||
};
|
||||
|
||||
associations.removed = mkOption {
|
||||
type = types.attrsOf strListOrSingleton;
|
||||
default = { };
|
||||
example = { "mimetype1" = "foo5.desktop"; };
|
||||
description = ''
|
||||
Removes associations of applications with mimetypes, as if the
|
||||
.desktop file was <emphasis>not</emphasis> listing this
|
||||
mimetype in the first place.
|
||||
'';
|
||||
};
|
||||
|
||||
defaultApplications = mkOption {
|
||||
type = types.attrsOf strListOrSingleton;
|
||||
default = { };
|
||||
example = literalExample ''
|
||||
{
|
||||
"mimetype1" = [ "default1.desktop" "default2.desktop" ];
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
The default application to be used for a given mimetype. This
|
||||
is, for instance, the one that will be started when
|
||||
double-clicking on a file in a file manager. If the
|
||||
application is no longer installed, the next application in
|
||||
the list is attempted, and so on.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Deprecated but still used by some applications.
|
||||
xdg.dataFile."applications/mimeapps.list".source =
|
||||
config.xdg.configFile."mimeapps.list".source;
|
||||
|
||||
xdg.configFile."mimeapps.list".text =
|
||||
let joinValues = mapAttrs (n: concatStringsSep ";");
|
||||
in generators.toINI { } {
|
||||
"Added Associations" = joinValues cfg.associations.added;
|
||||
"Removed Associations" = joinValues cfg.associations.removed;
|
||||
"Default Applications" = joinValues cfg.defaultApplications;
|
||||
};
|
||||
};
|
||||
}
|
||||
55
modules/misc/xdg-mime.nix
Normal file
55
modules/misc/xdg-mime.nix
Normal file
@@ -0,0 +1,55 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.xdg.mime;
|
||||
|
||||
in {
|
||||
options = {
|
||||
xdg.mime.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to install programs and files to support the
|
||||
XDG Shared MIME-info specification and XDG MIME Applications
|
||||
specification at
|
||||
<link xlink:href="https://specifications.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html"/>
|
||||
and
|
||||
<link xlink:href="https://specifications.freedesktop.org/mime-apps-spec/mime-apps-spec-latest.html"/>,
|
||||
respectively.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf config.xdg.mime.enable {
|
||||
home.packages = [
|
||||
# Explicitly install package to provide basic mime types.
|
||||
pkgs.shared-mime-info
|
||||
|
||||
# Make sure the target directories will be real directories.
|
||||
(pkgs.runCommandLocal "dummy-xdg-mime-dirs1" { } ''
|
||||
mkdir -p $out/share/{applications,mime/packages}
|
||||
'')
|
||||
(pkgs.runCommandLocal "dummy-xdg-mime-dirs2" { } ''
|
||||
mkdir -p $out/share/{applications,mime/packages}
|
||||
'')
|
||||
];
|
||||
|
||||
home.extraProfileCommands = ''
|
||||
if [[ -w $out/share/mime && -w $out/share/mime/packages && -d $out/share/mime/packages ]]; then
|
||||
XDG_DATA_DIRS=$out/share \
|
||||
PKGSYSTEM_ENABLE_FSYNC=0 \
|
||||
${pkgs.buildPackages.shared-mime-info}/bin/update-mime-database \
|
||||
-V $out/share/mime > /dev/null
|
||||
fi
|
||||
|
||||
if [[ -w $out/share/applications ]]; then
|
||||
${pkgs.buildPackages.desktop-file-utils}/bin/update-desktop-database \
|
||||
$out/share/applications
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
}
|
||||
121
modules/misc/xdg-user-dirs.nix
Normal file
121
modules/misc/xdg-user-dirs.nix
Normal file
@@ -0,0 +1,121 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.xdg.userDirs;
|
||||
|
||||
in {
|
||||
meta.maintainers = with maintainers; [ pacien ];
|
||||
|
||||
imports = [
|
||||
(mkRenamedOptionModule [ "xdg" "userDirs" "publishShare" ] [
|
||||
"xdg"
|
||||
"userDirs"
|
||||
"publicShare"
|
||||
])
|
||||
];
|
||||
|
||||
options.xdg.userDirs = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to manage <filename>$XDG_CONFIG_HOME/user-dirs.dirs</filename>.
|
||||
</para>
|
||||
<para>
|
||||
The generated file is read-only.
|
||||
'';
|
||||
};
|
||||
|
||||
# Well-known directory list from
|
||||
# https://gitlab.freedesktop.org/xdg/xdg-user-dirs/blob/master/man/user-dirs.dirs.xml
|
||||
|
||||
desktop = mkOption {
|
||||
type = types.str;
|
||||
default = "$HOME/Desktop";
|
||||
description = "The Desktop directory.";
|
||||
};
|
||||
|
||||
documents = mkOption {
|
||||
type = types.str;
|
||||
default = "$HOME/Documents";
|
||||
description = "The Documents directory.";
|
||||
};
|
||||
|
||||
download = mkOption {
|
||||
type = types.str;
|
||||
default = "$HOME/Downloads";
|
||||
description = "The Downloads directory.";
|
||||
};
|
||||
|
||||
music = mkOption {
|
||||
type = types.str;
|
||||
default = "$HOME/Music";
|
||||
description = "The Music directory.";
|
||||
};
|
||||
|
||||
pictures = mkOption {
|
||||
type = types.str;
|
||||
default = "$HOME/Pictures";
|
||||
description = "The Pictures directory.";
|
||||
};
|
||||
|
||||
publicShare = mkOption {
|
||||
type = types.str;
|
||||
default = "$HOME/Public";
|
||||
description = "The Public share directory.";
|
||||
};
|
||||
|
||||
templates = mkOption {
|
||||
type = types.str;
|
||||
default = "$HOME/Templates";
|
||||
description = "The Templates directory.";
|
||||
};
|
||||
|
||||
videos = mkOption {
|
||||
type = types.str;
|
||||
default = "$HOME/Videos";
|
||||
description = "The Videos directory.";
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = with types; attrsOf str;
|
||||
default = { };
|
||||
example = { XDG_MISC_DIR = "$HOME/Misc"; };
|
||||
description = "Other user directories.";
|
||||
};
|
||||
|
||||
createDirectories =
|
||||
mkEnableOption "automatic creation of the XDG user directories";
|
||||
};
|
||||
|
||||
config = let
|
||||
directories = {
|
||||
XDG_DESKTOP_DIR = cfg.desktop;
|
||||
XDG_DOCUMENTS_DIR = cfg.documents;
|
||||
XDG_DOWNLOAD_DIR = cfg.download;
|
||||
XDG_MUSIC_DIR = cfg.music;
|
||||
XDG_PICTURES_DIR = cfg.pictures;
|
||||
XDG_PUBLICSHARE_DIR = cfg.publicShare;
|
||||
XDG_TEMPLATES_DIR = cfg.templates;
|
||||
XDG_VIDEOS_DIR = cfg.videos;
|
||||
} // cfg.extraConfig;
|
||||
in mkIf cfg.enable {
|
||||
xdg.configFile."user-dirs.dirs".text = let
|
||||
# For some reason, these need to be wrapped with quotes to be valid.
|
||||
wrapped = mapAttrs (_: value: ''"${value}"'') directories;
|
||||
in generators.toKeyValue { } wrapped;
|
||||
|
||||
xdg.configFile."user-dirs.conf".text = "enabled=False";
|
||||
|
||||
home.activation = mkIf cfg.createDirectories {
|
||||
createXdgUserDirectories = let
|
||||
directoriesList = attrValues directories;
|
||||
mkdir = (dir: ''$DRY_RUN_CMD mkdir -p $VERBOSE_ARG "${dir}"'');
|
||||
in lib.hm.dag.entryAfter [ "writeBoundary" ]
|
||||
(strings.concatMapStringsSep "\n" mkdir directoriesList);
|
||||
};
|
||||
};
|
||||
}
|
||||
114
modules/misc/xdg.nix
Normal file
114
modules/misc/xdg.nix
Normal file
@@ -0,0 +1,114 @@
|
||||
{ options, config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.xdg;
|
||||
|
||||
dag = config.lib.dag;
|
||||
|
||||
fileType = (import ../lib/file-type.nix {
|
||||
inherit (config.home) homeDirectory;
|
||||
inherit lib pkgs;
|
||||
}).fileType;
|
||||
|
||||
defaultCacheHome = "${config.home.homeDirectory}/.cache";
|
||||
defaultConfigHome = "${config.home.homeDirectory}/.config";
|
||||
defaultDataHome = "${config.home.homeDirectory}/.local/share";
|
||||
|
||||
getXdgDir = name: fallback:
|
||||
let
|
||||
value = builtins.getEnv name;
|
||||
in
|
||||
if value != "" then value else fallback;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
options.xdg = {
|
||||
enable = mkEnableOption "management of XDG base directories";
|
||||
|
||||
cacheHome = mkOption {
|
||||
type = types.path;
|
||||
defaultText = "~/.cache";
|
||||
description = ''
|
||||
Absolute path to directory holding application caches.
|
||||
'';
|
||||
};
|
||||
|
||||
configFile = mkOption {
|
||||
type = fileType "<varname>xdg.configHome</varname>" cfg.configHome;
|
||||
default = {};
|
||||
description = ''
|
||||
Attribute set of files to link into the user's XDG
|
||||
configuration home.
|
||||
'';
|
||||
};
|
||||
|
||||
configHome = mkOption {
|
||||
type = types.path;
|
||||
defaultText = "~/.config";
|
||||
description = ''
|
||||
Absolute path to directory holding application configurations.
|
||||
'';
|
||||
};
|
||||
|
||||
dataFile = mkOption {
|
||||
type = fileType "<varname>xdg.dataHome</varname>" cfg.dataHome;
|
||||
default = {};
|
||||
description = ''
|
||||
Attribute set of files to link into the user's XDG
|
||||
data home.
|
||||
'';
|
||||
};
|
||||
|
||||
dataHome = mkOption {
|
||||
type = types.path;
|
||||
defaultText = "~/.local/share";
|
||||
description = ''
|
||||
Absolute path to directory holding application data.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkMerge [
|
||||
(mkIf cfg.enable {
|
||||
xdg.cacheHome = mkDefault defaultCacheHome;
|
||||
xdg.configHome = mkDefault defaultConfigHome;
|
||||
xdg.dataHome = mkDefault defaultDataHome;
|
||||
|
||||
home.sessionVariables = {
|
||||
XDG_CACHE_HOME = cfg.cacheHome;
|
||||
XDG_CONFIG_HOME = cfg.configHome;
|
||||
XDG_DATA_HOME = cfg.dataHome;
|
||||
};
|
||||
})
|
||||
|
||||
# Legacy non-deterministic setup.
|
||||
(mkIf (!cfg.enable && versionOlder config.home.stateVersion "20.09") {
|
||||
xdg.cacheHome = getXdgDir "XDG_CACHE_HOME" defaultCacheHome;
|
||||
xdg.configHome = getXdgDir "XDG_CONFIG_HOME" defaultConfigHome;
|
||||
xdg.dataHome = getXdgDir "XDG_DATA_HOME" defaultDataHome;
|
||||
})
|
||||
|
||||
# "Modern" deterministic setup.
|
||||
(mkIf (!cfg.enable && versionAtLeast config.home.stateVersion "20.09") {
|
||||
xdg.cacheHome = mkDefault defaultCacheHome;
|
||||
xdg.configHome = mkDefault defaultConfigHome;
|
||||
xdg.dataHome = mkDefault defaultDataHome;
|
||||
})
|
||||
|
||||
{
|
||||
home.file = mkMerge [
|
||||
(mapAttrs'
|
||||
(name: file: nameValuePair "${config.xdg.configHome}/${name}" file)
|
||||
cfg.configFile)
|
||||
(mapAttrs'
|
||||
(name: file: nameValuePair "${config.xdg.dataHome}/${name}" file)
|
||||
cfg.dataFile)
|
||||
{ "${config.xdg.cacheHome}/.keep".text = ""; }
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
237
modules/modules.nix
Normal file
237
modules/modules.nix
Normal file
@@ -0,0 +1,237 @@
|
||||
{ pkgs
|
||||
|
||||
# Note, this should be "the standard library" + HM extensions.
|
||||
, lib
|
||||
|
||||
# Whether to enable module type checking.
|
||||
, check ? true
|
||||
|
||||
# If disabled, the pkgs attribute passed to this function is used instead.
|
||||
, useNixpkgsModule ? true
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
hostPlatform = pkgs.stdenv.hostPlatform;
|
||||
|
||||
loadModule = file: { condition ? true }: {
|
||||
inherit file condition;
|
||||
};
|
||||
|
||||
allModules = [
|
||||
(loadModule ./accounts/email.nix { })
|
||||
(loadModule ./config/i18n.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./files.nix { })
|
||||
(loadModule ./home-environment.nix { })
|
||||
(loadModule ./manual.nix { })
|
||||
(loadModule ./misc/dconf.nix { })
|
||||
(loadModule ./misc/debug.nix { })
|
||||
(loadModule ./misc/fontconfig.nix { })
|
||||
(loadModule ./misc/gtk.nix { })
|
||||
(loadModule ./misc/lib.nix { })
|
||||
(loadModule ./misc/news.nix { })
|
||||
(loadModule ./misc/nixpkgs.nix { condition = useNixpkgsModule; })
|
||||
(loadModule ./misc/numlock.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./misc/pam.nix { })
|
||||
(loadModule ./misc/qt.nix { })
|
||||
(loadModule ./misc/submodule-support.nix { })
|
||||
(loadModule ./misc/tmpfiles.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./misc/version.nix { })
|
||||
(loadModule ./misc/vte.nix { })
|
||||
(loadModule ./misc/xdg-mime.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./misc/xdg-mime-apps.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./misc/xdg-user-dirs.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./misc/xdg.nix { })
|
||||
(loadModule ./programs/abook.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./programs/afew.nix { })
|
||||
(loadModule ./programs/alacritty.nix { })
|
||||
(loadModule ./programs/alot.nix { })
|
||||
(loadModule ./programs/aria2.nix { })
|
||||
(loadModule ./programs/astroid.nix { })
|
||||
(loadModule ./programs/autojump.nix { })
|
||||
(loadModule ./programs/autorandr.nix { })
|
||||
(loadModule ./programs/bash.nix { })
|
||||
(loadModule ./programs/bat.nix { })
|
||||
(loadModule ./programs/beets.nix { })
|
||||
(loadModule ./programs/broot.nix { })
|
||||
(loadModule ./programs/browserpass.nix { })
|
||||
(loadModule ./programs/chromium.nix { })
|
||||
(loadModule ./programs/command-not-found/command-not-found.nix { })
|
||||
(loadModule ./programs/dircolors.nix { })
|
||||
(loadModule ./programs/direnv.nix { })
|
||||
(loadModule ./programs/eclipse.nix { })
|
||||
(loadModule ./programs/emacs.nix { })
|
||||
(loadModule ./programs/feh.nix { })
|
||||
(loadModule ./programs/firefox.nix { })
|
||||
(loadModule ./programs/fish.nix { })
|
||||
(loadModule ./programs/fzf.nix { })
|
||||
(loadModule ./programs/getmail.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./programs/gh.nix { })
|
||||
(loadModule ./programs/git.nix { })
|
||||
(loadModule ./programs/gnome-terminal.nix { })
|
||||
(loadModule ./programs/go.nix { })
|
||||
(loadModule ./programs/gpg.nix { })
|
||||
(loadModule ./programs/home-manager.nix { })
|
||||
(loadModule ./programs/htop.nix { })
|
||||
(loadModule ./programs/i3status.nix { })
|
||||
(loadModule ./programs/i3status-rust.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./programs/info.nix { })
|
||||
(loadModule ./programs/irssi.nix { })
|
||||
(loadModule ./programs/lieer.nix { })
|
||||
(loadModule ./programs/jq.nix { })
|
||||
(loadModule ./programs/kakoune.nix { })
|
||||
(loadModule ./programs/keychain.nix { })
|
||||
(loadModule ./programs/kitty.nix { })
|
||||
(loadModule ./programs/lesspipe.nix { })
|
||||
(loadModule ./programs/lf.nix { })
|
||||
(loadModule ./programs/lsd.nix { })
|
||||
(loadModule ./programs/man.nix { })
|
||||
(loadModule ./programs/matplotlib.nix { })
|
||||
(loadModule ./programs/mbsync.nix { })
|
||||
(loadModule ./programs/mcfly.nix { })
|
||||
(loadModule ./programs/mercurial.nix { })
|
||||
(loadModule ./programs/mpv.nix { })
|
||||
(loadModule ./programs/msmtp.nix { })
|
||||
(loadModule ./programs/mu.nix { })
|
||||
(loadModule ./programs/ncmpcpp.nix { })
|
||||
(loadModule ./programs/ne.nix { })
|
||||
(loadModule ./programs/neomutt.nix { })
|
||||
(loadModule ./programs/neovim.nix { })
|
||||
(loadModule ./programs/newsboat.nix { })
|
||||
(loadModule ./programs/noti.nix { })
|
||||
(loadModule ./programs/notmuch.nix { })
|
||||
(loadModule ./programs/nushell.nix { })
|
||||
(loadModule ./programs/obs-studio.nix { })
|
||||
(loadModule ./programs/octant.nix { })
|
||||
(loadModule ./programs/offlineimap.nix { })
|
||||
(loadModule ./programs/opam.nix { })
|
||||
(loadModule ./programs/password-store.nix { })
|
||||
(loadModule ./programs/pazi.nix { })
|
||||
(loadModule ./programs/pet.nix { })
|
||||
(loadModule ./programs/pidgin.nix { })
|
||||
(loadModule ./programs/powerline-go.nix { })
|
||||
(loadModule ./programs/qutebrowser.nix { })
|
||||
(loadModule ./programs/readline.nix { })
|
||||
(loadModule ./programs/rofi.nix { })
|
||||
(loadModule ./programs/rofi-pass.nix { })
|
||||
(loadModule ./programs/rtorrent.nix { })
|
||||
(loadModule ./programs/skim.nix { })
|
||||
(loadModule ./programs/starship.nix { })
|
||||
(loadModule ./programs/sbt.nix { })
|
||||
(loadModule ./programs/ssh.nix { })
|
||||
(loadModule ./programs/taskwarrior.nix { })
|
||||
(loadModule ./programs/termite.nix { })
|
||||
(loadModule ./programs/texlive.nix { })
|
||||
(loadModule ./programs/tmux.nix { })
|
||||
(loadModule ./programs/urxvt.nix { })
|
||||
(loadModule ./programs/vim.nix { })
|
||||
(loadModule ./programs/vscode.nix { })
|
||||
(loadModule ./programs/vscode/haskell.nix { })
|
||||
(loadModule ./programs/waybar.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./programs/z-lua.nix { })
|
||||
(loadModule ./programs/zathura.nix { })
|
||||
(loadModule ./programs/zoxide.nix { })
|
||||
(loadModule ./programs/zplug.nix { })
|
||||
(loadModule ./programs/zsh.nix { })
|
||||
(loadModule ./programs/zsh/prezto.nix { })
|
||||
(loadModule ./services/blueman-applet.nix { })
|
||||
(loadModule ./services/caffeine.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/cbatticon.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/clipmenu.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/compton.nix { })
|
||||
(loadModule ./services/dropbox.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/dunst.nix { })
|
||||
(loadModule ./services/dwm-status.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/emacs.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/flameshot.nix { })
|
||||
(loadModule ./services/fluidsynth.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/redshift-gammastep/gammastep.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/getmail.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/gnome-keyring.nix { })
|
||||
(loadModule ./services/gpg-agent.nix { })
|
||||
(loadModule ./services/grobi.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/hound.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/imapnotify.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/kanshi.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/kbfs.nix { })
|
||||
(loadModule ./services/kdeconnect.nix { })
|
||||
(loadModule ./services/keepassx.nix { })
|
||||
(loadModule ./services/keybase.nix { })
|
||||
(loadModule ./services/keynav.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/lieer.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/lorri.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/mako.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/mbsync.nix { })
|
||||
(loadModule ./services/mpd.nix { })
|
||||
(loadModule ./services/mpdris2.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/muchsync.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/network-manager-applet.nix { })
|
||||
(loadModule ./services/nextcloud-client.nix { })
|
||||
(loadModule ./services/owncloud-client.nix { })
|
||||
(loadModule ./services/parcellite.nix { })
|
||||
(loadModule ./services/password-store-sync.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/pasystray.nix { })
|
||||
(loadModule ./services/pbgopy.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/picom.nix { })
|
||||
(loadModule ./services/plan9port.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/playerctld.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/polybar.nix { })
|
||||
(loadModule ./services/pulseeffects.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/random-background.nix { })
|
||||
(loadModule ./services/redshift-gammastep/redshift.nix { })
|
||||
(loadModule ./services/rsibreak.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/screen-locker.nix { })
|
||||
(loadModule ./services/stalonetray.nix { })
|
||||
(loadModule ./services/status-notifier-watcher.nix { })
|
||||
(loadModule ./services/spotifyd.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/sxhkd.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/syncthing.nix { })
|
||||
(loadModule ./services/taffybar.nix { })
|
||||
(loadModule ./services/tahoe-lafs.nix { })
|
||||
(loadModule ./services/taskwarrior-sync.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/udiskie.nix { })
|
||||
(loadModule ./services/unclutter.nix { })
|
||||
(loadModule ./services/unison.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/window-managers/awesome.nix { })
|
||||
(loadModule ./services/window-managers/bspwm/default.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/window-managers/i3-sway/i3.nix { })
|
||||
(loadModule ./services/window-managers/i3-sway/sway.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/window-managers/xmonad.nix { })
|
||||
(loadModule ./services/wlsunset.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/xcape.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/xembed-sni-proxy.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./services/xscreensaver.nix { })
|
||||
(loadModule ./services/xsuspender.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./systemd.nix { })
|
||||
(loadModule ./targets/darwin { condition = hostPlatform.isDarwin; })
|
||||
(loadModule ./targets/generic-linux.nix { condition = hostPlatform.isLinux; })
|
||||
(loadModule ./xcursor.nix { })
|
||||
(loadModule ./xresources.nix { })
|
||||
(loadModule ./xsession.nix { })
|
||||
(loadModule (pkgs.path + "/nixos/modules/misc/assertions.nix") { })
|
||||
(loadModule (pkgs.path + "/nixos/modules/misc/meta.nix") { })
|
||||
];
|
||||
|
||||
modules = map (getAttr "file") (filter (getAttr "condition") allModules);
|
||||
|
||||
pkgsModule = { config, ... }: {
|
||||
config = {
|
||||
_module.args.baseModules = modules;
|
||||
_module.args.pkgsPath = lib.mkDefault (
|
||||
if versionAtLeast config.home.stateVersion "20.09" then
|
||||
pkgs.path
|
||||
else
|
||||
<nixpkgs>);
|
||||
_module.args.pkgs = lib.mkDefault pkgs;
|
||||
_module.check = check;
|
||||
lib = lib.hm;
|
||||
} // optionalAttrs useNixpkgsModule {
|
||||
nixpkgs.system = mkDefault pkgs.system;
|
||||
};
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
modules ++ [ pkgsModule ]
|
||||
40
modules/programs/abook.nix
Normal file
40
modules/programs/abook.nix
Normal file
@@ -0,0 +1,40 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.programs.abook;
|
||||
|
||||
in {
|
||||
options.programs.abook = {
|
||||
enable = mkEnableOption "Abook";
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = ''
|
||||
field pager = Pager
|
||||
view CONTACT = name, email
|
||||
set autosave=true
|
||||
'';
|
||||
description = ''
|
||||
Extra lines added to <filename>$HOME/.config/abook/abookrc</filename>.
|
||||
Available configuration options are described in the abook repository:
|
||||
<link xlink:href="https://sourceforge.net/p/abook/git/ci/master/tree/sample.abookrc" />.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
home.packages = [ pkgs.abook ];
|
||||
xdg.configFile."abook/abookrc" = mkIf (cfg.extraConfig != "") {
|
||||
text = ''
|
||||
# Generated by Home Manager.
|
||||
# See http://abook.sourceforge.net/
|
||||
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
52
modules/programs/afew.nix
Normal file
52
modules/programs/afew.nix
Normal file
@@ -0,0 +1,52 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.programs.afew;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
options.programs.afew = {
|
||||
enable = mkEnableOption "the afew initial tagging script for Notmuch";
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = ''
|
||||
[SpamFilter]
|
||||
[KillThreadsFilter]
|
||||
[ListMailsFilter]
|
||||
[ArchiveSentMailsFilter]
|
||||
[InboxFilter]
|
||||
'';
|
||||
example = ''
|
||||
[SpamFilter]
|
||||
|
||||
[Filter.0]
|
||||
query = from:pointyheaded@boss.com
|
||||
tags = -new;+boss
|
||||
message = Message from above
|
||||
|
||||
[InboxFilter]
|
||||
'';
|
||||
description = ''
|
||||
Extra lines added to afew configuration file. Available
|
||||
configuration options are described in the afew manual:
|
||||
<link xlink:href="https://afew.readthedocs.io/en/latest/configuration.html" />.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
home.packages = [ pkgs.afew ];
|
||||
|
||||
xdg.configFile."afew/config".text = ''
|
||||
# Generated by Home Manager.
|
||||
# See https://afew.readthedocs.io/
|
||||
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
};
|
||||
}
|
||||
63
modules/programs/alacritty.nix
Normal file
63
modules/programs/alacritty.nix
Normal file
@@ -0,0 +1,63 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.programs.alacritty;
|
||||
yamlFormat = pkgs.formats.yaml { };
|
||||
in {
|
||||
options = {
|
||||
programs.alacritty = {
|
||||
enable = mkEnableOption "Alacritty";
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.alacritty;
|
||||
defaultText = literalExample "pkgs.alacritty";
|
||||
description = "The Alacritty package to install.";
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = yamlFormat.type;
|
||||
default = { };
|
||||
example = literalExample ''
|
||||
{
|
||||
window.dimensions = {
|
||||
lines = 3;
|
||||
columns = 200;
|
||||
};
|
||||
key_bindings = [
|
||||
{
|
||||
key = "K";
|
||||
mods = "Control";
|
||||
chars = "\\x0c";
|
||||
}
|
||||
];
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
Configuration written to
|
||||
<filename>~/.config/alacritty/alacritty.yml</filename>. See
|
||||
<link xlink:href="https://github.com/jwilm/alacritty/blob/master/alacritty.yml"/>
|
||||
for the default configuration.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkMerge [
|
||||
(mkIf cfg.enable {
|
||||
home.packages = [ cfg.package ];
|
||||
|
||||
xdg.configFile."alacritty/alacritty.yml" = mkIf (cfg.settings != { }) {
|
||||
# TODO: Replace by the generate function but need to figure out how to
|
||||
# handle the escaping first.
|
||||
#
|
||||
# source = yamlFormat.generate "alacritty.yml" cfg.settings;
|
||||
|
||||
text =
|
||||
replaceStrings [ "\\\\" ] [ "\\" ] (builtins.toJSON cfg.settings);
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||
58
modules/programs/alot-accounts.nix
Normal file
58
modules/programs/alot-accounts.nix
Normal file
@@ -0,0 +1,58 @@
|
||||
pkgs:
|
||||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
options.alot = {
|
||||
sendMailCommand = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
description = ''
|
||||
Command to send a mail. If msmtp is enabled for the account,
|
||||
then this is set to
|
||||
<command>msmtpq --read-envelope-from --read-recipients</command>.
|
||||
'';
|
||||
};
|
||||
|
||||
contactCompletion = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = {
|
||||
type = "shellcommand";
|
||||
command =
|
||||
"'${pkgs.notmuch}/bin/notmuch address --format=json --output=recipients date:6M..'";
|
||||
regexp = "'\\[?{" + ''
|
||||
"name": "(?P<name>.*)", "address": "(?P<email>.+)", "name-addr": ".*"''
|
||||
+ "}[,\\]]?'";
|
||||
shellcommand_external_filtering = "False";
|
||||
};
|
||||
example = literalExample ''
|
||||
{
|
||||
type = "shellcommand";
|
||||
command = "abook --mutt-query";
|
||||
regexp = "'^(?P<email>[^@]+@[^\t]+)\t+(?P<name>[^\t]+)'";
|
||||
ignorecase = "True";
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
Contact completion configuration as expected per alot.
|
||||
See <link xlink:href="http://alot.readthedocs.io/en/latest/configuration/contacts_completion.html">alot's wiki</link> for
|
||||
explanation about possible values.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Extra settings to add to this Alot account configuration.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf config.notmuch.enable {
|
||||
alot.sendMailCommand = mkOptionDefault (if config.msmtp.enable then
|
||||
"msmtpq --read-envelope-from --read-recipients"
|
||||
else
|
||||
null);
|
||||
};
|
||||
}
|
||||
240
modules/programs/alot.nix
Normal file
240
modules/programs/alot.nix
Normal file
@@ -0,0 +1,240 @@
|
||||
# alot config loader is sensitive to leading space !
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.programs.alot;
|
||||
|
||||
enabledAccounts =
|
||||
filter (a: a.notmuch.enable) (attrValues config.accounts.email.accounts);
|
||||
|
||||
# sorted: primary first
|
||||
alotAccounts = sort (a: b: !(a.primary -> b.primary)) enabledAccounts;
|
||||
|
||||
boolStr = v: if v then "True" else "False";
|
||||
|
||||
mkKeyValue = key: value:
|
||||
let value' = if isBool value then boolStr value else toString value;
|
||||
in "${key} = ${value'}";
|
||||
|
||||
mk2ndLevelSectionName = name: "[" + name + "]";
|
||||
|
||||
tagSubmodule = types.submodule {
|
||||
options = {
|
||||
translated = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
description = ''
|
||||
Fixed string representation for this tag. The tag can be
|
||||
hidden from view, if the key translated is set to
|
||||
<literal>""</literal>, the empty string.
|
||||
'';
|
||||
};
|
||||
|
||||
translation = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
A pair of strings that define a regular substitution to
|
||||
compute the string representation on the fly using
|
||||
<literal>re.sub</literal>.
|
||||
'';
|
||||
};
|
||||
|
||||
normal = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "'','', 'white','light red', 'white','#d66'";
|
||||
description = ''
|
||||
How to display the tag when unfocused.
|
||||
See <link xlink:href="https://alot.readthedocs.io/en/latest/configuration/theming.html#tagstring-formatting"/>.
|
||||
'';
|
||||
};
|
||||
|
||||
focus = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "How to display the tag when focused.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
accountStr = account:
|
||||
with account;
|
||||
concatStringsSep "\n" ([ "[[${name}]]" ]
|
||||
++ mapAttrsToList (n: v: n + "=" + v) ({
|
||||
address = address;
|
||||
realname = realName;
|
||||
sendmail_command =
|
||||
optionalString (alot.sendMailCommand != null) alot.sendMailCommand;
|
||||
sent_box = "maildir" + "://" + maildir.absPath + "/" + folders.sent;
|
||||
draft_box = "maildir" + "://" + maildir.absPath + "/" + folders.drafts;
|
||||
} // optionalAttrs (aliases != [ ]) {
|
||||
aliases = concatStringsSep "," aliases;
|
||||
} // optionalAttrs (gpg != null) {
|
||||
gpg_key = gpg.key;
|
||||
encrypt_by_default = if gpg.encryptByDefault then "all" else "none";
|
||||
sign_by_default = boolStr gpg.signByDefault;
|
||||
} // optionalAttrs (signature.showSignature != "none") {
|
||||
signature = pkgs.writeText "signature.txt" signature.text;
|
||||
signature_as_attachment = boolStr (signature.showSignature == "attach");
|
||||
}) ++ [ alot.extraConfig ] ++ [ "[[[abook]]]" ]
|
||||
++ mapAttrsToList (n: v: n + "=" + v) alot.contactCompletion);
|
||||
|
||||
configFile = let
|
||||
bindingsToStr = attrSet:
|
||||
concatStringsSep "\n" (mapAttrsToList (n: v: "${n} = ${v}") attrSet);
|
||||
in ''
|
||||
# Generated by Home Manager.
|
||||
# See http://alot.readthedocs.io/en/latest/configuration/config_options.html
|
||||
|
||||
${generators.toKeyValue { inherit mkKeyValue; } cfg.settings}
|
||||
${cfg.extraConfig}
|
||||
[tags]
|
||||
'' + (let
|
||||
submoduleToAttrs = m:
|
||||
filterAttrs (name: v: name != "_module" && v != null) m;
|
||||
in generators.toINI { mkSectionName = mk2ndLevelSectionName; }
|
||||
(mapAttrs (name: x: submoduleToAttrs x) cfg.tags)) + ''
|
||||
[bindings]
|
||||
${bindingsToStr cfg.bindings.global}
|
||||
|
||||
[[bufferlist]]
|
||||
${bindingsToStr cfg.bindings.bufferlist}
|
||||
[[search]]
|
||||
${bindingsToStr cfg.bindings.search}
|
||||
[[envelope]]
|
||||
${bindingsToStr cfg.bindings.envelope}
|
||||
[[taglist]]
|
||||
${bindingsToStr cfg.bindings.taglist}
|
||||
[[thread]]
|
||||
${bindingsToStr cfg.bindings.thread}
|
||||
|
||||
[accounts]
|
||||
|
||||
${concatStringsSep "\n\n" (map accountStr alotAccounts)}
|
||||
'';
|
||||
|
||||
in {
|
||||
options = {
|
||||
programs.alot = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
example = true;
|
||||
description = ''
|
||||
Whether to enable the Alot mail user agent. Alot uses the
|
||||
Notmuch email system and will therefore be automatically
|
||||
enabled for each email account that is managed by Notmuch.
|
||||
'';
|
||||
};
|
||||
|
||||
hooks = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Content of the hooks file.
|
||||
'';
|
||||
};
|
||||
|
||||
bindings = mkOption {
|
||||
type = types.submodule {
|
||||
options = {
|
||||
global = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = { };
|
||||
description = "Global keybindings.";
|
||||
};
|
||||
|
||||
bufferlist = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = { };
|
||||
description = "Bufferlist mode keybindings.";
|
||||
};
|
||||
|
||||
search = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = { };
|
||||
description = "Search mode keybindings.";
|
||||
};
|
||||
|
||||
envelope = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = { };
|
||||
description = "Envelope mode keybindings.";
|
||||
};
|
||||
|
||||
taglist = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = { };
|
||||
description = "Taglist mode keybindings.";
|
||||
};
|
||||
|
||||
thread = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = { };
|
||||
description = "Thread mode keybindings.";
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
description = ''
|
||||
Keybindings.
|
||||
'';
|
||||
};
|
||||
|
||||
tags = mkOption {
|
||||
type = types.attrsOf tagSubmodule;
|
||||
default = { };
|
||||
description = "How to display the tags.";
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = with types;
|
||||
let primitive = either (either (either str int) bool) float;
|
||||
in attrsOf primitive;
|
||||
default = {
|
||||
initial_command = "search tag:inbox AND NOT tag:killed";
|
||||
auto_remove_unread = true;
|
||||
handle_mouse = true;
|
||||
prefer_plaintext = true;
|
||||
};
|
||||
example = literalExample ''
|
||||
{
|
||||
auto_remove_unread = true;
|
||||
ask_subject = false;
|
||||
thread_indent_replies = 2;
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
Configuration options added to alot configuration file.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Extra lines added to alot configuration file.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
accounts.email.accounts = mkOption {
|
||||
type = with types; attrsOf (submodule (import ./alot-accounts.nix pkgs));
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
home.packages = [ pkgs.alot ];
|
||||
|
||||
xdg.configFile."alot/config".text = configFile;
|
||||
|
||||
xdg.configFile."alot/hooks.py" = mkIf (cfg.hooks != "") {
|
||||
text = ''
|
||||
# Generated by Home Manager.
|
||||
'' + cfg.hooks;
|
||||
};
|
||||
};
|
||||
}
|
||||
61
modules/programs/aria2.nix
Normal file
61
modules/programs/aria2.nix
Normal file
@@ -0,0 +1,61 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.programs.aria2;
|
||||
|
||||
formatLine = n: v:
|
||||
let
|
||||
formatValue = v:
|
||||
if builtins.isBool v then
|
||||
(if v then "true" else "false")
|
||||
else
|
||||
toString v;
|
||||
in "${n}=${formatValue v}";
|
||||
in {
|
||||
meta.maintainers = [ hm.maintainers.justinlovinger ];
|
||||
|
||||
options.programs.aria2 = {
|
||||
enable = mkEnableOption "aria2";
|
||||
|
||||
settings = mkOption {
|
||||
type = with types; attrsOf (oneOf [ bool float int str ]);
|
||||
default = { };
|
||||
description = ''
|
||||
Options to add to <filename>aria2.conf</filename> file.
|
||||
See
|
||||
<citerefentry>
|
||||
<refentrytitle>aria2c</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry>
|
||||
for options.
|
||||
'';
|
||||
example = literalExample ''
|
||||
{
|
||||
listen-port = 60000;
|
||||
dht-listen-port = 60000;
|
||||
seed-ratio = 1.0;
|
||||
max-upload-limit = "50K";
|
||||
ftp-pasv = true;
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Extra lines added to <filename>aria2.conf</filename> file.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
home.packages = [ pkgs.aria2 ];
|
||||
|
||||
xdg.configFile."aria2/aria2.conf".text = concatStringsSep "\n" ([ ]
|
||||
++ mapAttrsToList formatLine cfg.settings
|
||||
++ optional (cfg.extraConfig != "") cfg.extraConfig);
|
||||
};
|
||||
}
|
||||
32
modules/programs/astroid-accounts.nix
Normal file
32
modules/programs/astroid-accounts.nix
Normal file
@@ -0,0 +1,32 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
options.astroid = {
|
||||
enable = mkEnableOption "Astroid";
|
||||
|
||||
sendMailCommand = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Command to send a mail. If msmtp is enabled for the account,
|
||||
then this is set to
|
||||
<command>msmtpq --read-envelope-from --read-recipients</command>.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.attrsOf types.anything;
|
||||
default = { };
|
||||
example = { select_query = ""; };
|
||||
description = ''
|
||||
Extra settings to add to this astroid account configuration.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf config.notmuch.enable {
|
||||
astroid.sendMailCommand = mkIf config.msmtp.enable
|
||||
(mkOptionDefault "msmtpq --read-envelope-from --read-recipients");
|
||||
};
|
||||
}
|
||||
113
modules/programs/astroid-config-template.json
Normal file
113
modules/programs/astroid-config-template.json
Normal file
@@ -0,0 +1,113 @@
|
||||
{
|
||||
"astroid": {
|
||||
"config": {
|
||||
"version": "11"
|
||||
},
|
||||
"debug": {
|
||||
"dryrun_sending": "false"
|
||||
},
|
||||
"hints": {
|
||||
"level": "0"
|
||||
},
|
||||
"log": {
|
||||
"syslog": "false",
|
||||
"stdout": "true",
|
||||
"level": "info"
|
||||
}
|
||||
},
|
||||
"startup": {
|
||||
"queries": {
|
||||
"inbox": "tag:inbox"
|
||||
}
|
||||
},
|
||||
"terminal": {
|
||||
"height": "10",
|
||||
"font_description": "default"
|
||||
},
|
||||
"thread_index": {
|
||||
"page_jump_rows": "6",
|
||||
"sort_order": "newest",
|
||||
"cell": {
|
||||
"font_description": "default",
|
||||
"line_spacing": "2",
|
||||
"date_length": "10",
|
||||
"message_count_length": "4",
|
||||
"authors_length": "20",
|
||||
"subject_color": "#807d74",
|
||||
"subject_color_selected": "#000000",
|
||||
"background_color_selected": "",
|
||||
"background_color_marked": "#fff584",
|
||||
"background_color_marked_selected": "#bcb559",
|
||||
"tags_length": "80",
|
||||
"tags_upper_color": "#e5e5e5",
|
||||
"tags_lower_color": "#333333",
|
||||
"tags_alpha": "0.5",
|
||||
"hidden_tags": "attachment,flagged,unread"
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
"time": {
|
||||
"clock_format": "local",
|
||||
"same_year": "%b %-e",
|
||||
"diff_year": "%x"
|
||||
}
|
||||
},
|
||||
"editor": {
|
||||
"charset": "utf-8",
|
||||
"save_draft_on_force_quit": "true",
|
||||
"attachment_words": "attach",
|
||||
"attachment_directory": "~",
|
||||
"markdown_processor": "marked"
|
||||
},
|
||||
"mail": {
|
||||
"reply": {
|
||||
"quote_line": "Excerpts from %1's message of %2:",
|
||||
"mailinglist_reply_to_sender": "true"
|
||||
},
|
||||
"forward": {
|
||||
"quote_line": "Forwarding %1's message of %2:",
|
||||
"disposition": "inline"
|
||||
},
|
||||
"sent_tags": "sent",
|
||||
"message_id_fqdn": "",
|
||||
"message_id_user": "",
|
||||
"user_agent": "default",
|
||||
"send_delay": "2",
|
||||
"close_on_success": "false",
|
||||
"format_flowed": "false"
|
||||
},
|
||||
"poll": {
|
||||
"interval": "60",
|
||||
"always_full_refresh": "false"
|
||||
},
|
||||
"attachment": {
|
||||
"external_open_cmd": "xdg-open"
|
||||
},
|
||||
"thread_view": {
|
||||
"open_html_part_external": "false",
|
||||
"preferred_type": "plain",
|
||||
"preferred_html_only": "false",
|
||||
"allow_remote_when_encrypted": "false",
|
||||
"open_external_link": "xdg-open",
|
||||
"default_save_directory": "~",
|
||||
"indent_messages": "false",
|
||||
"gravatar": {
|
||||
"enable": "true"
|
||||
},
|
||||
"mark_unread_delay": "0.5",
|
||||
"expand_flagged": "true"
|
||||
},
|
||||
"crypto": {
|
||||
"gpg": {
|
||||
"path": "gpg2",
|
||||
"always_trust": "true",
|
||||
"enabled": "true"
|
||||
}
|
||||
},
|
||||
"saved_searches": {
|
||||
"show_on_startup": "false",
|
||||
"save_history": "true",
|
||||
"history_lines_to_show": "15",
|
||||
"history_lines": "1000"
|
||||
}
|
||||
}
|
||||
127
modules/programs/astroid.nix
Normal file
127
modules/programs/astroid.nix
Normal file
@@ -0,0 +1,127 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
with builtins;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.programs.astroid;
|
||||
|
||||
jsonFormat = pkgs.formats.json { };
|
||||
|
||||
astroidAccounts =
|
||||
filterAttrs (n: v: v.astroid.enable) config.accounts.email.accounts;
|
||||
|
||||
boolOpt = b: if b then "true" else "false";
|
||||
|
||||
accountAttr = account:
|
||||
with account;
|
||||
{
|
||||
email = address;
|
||||
name = realName;
|
||||
sendmail = astroid.sendMailCommand;
|
||||
additional_sent_tags = "";
|
||||
default = boolOpt primary;
|
||||
save_drafts_to = "${maildir.absPath}/${folders.drafts}";
|
||||
save_sent = "true";
|
||||
save_sent_to = "${maildir.absPath}/${folders.sent}";
|
||||
select_query = "";
|
||||
} // optionalAttrs (signature.showSignature != "none") {
|
||||
signature_attach = boolOpt (signature.showSignature == "attach");
|
||||
signature_default_on = boolOpt (signature.showSignature != "none");
|
||||
signature_file = pkgs.writeText "signature.txt" signature.text;
|
||||
signature_file_markdown = "false";
|
||||
signature_separate = "true"; # prepends '--\n' to the signature
|
||||
} // optionalAttrs (gpg != null) {
|
||||
always_gpg_sign = boolOpt gpg.signByDefault;
|
||||
gpgkey = gpg.key;
|
||||
} // astroid.extraConfig;
|
||||
|
||||
# See https://github.com/astroidmail/astroid/wiki/Configuration-Reference
|
||||
finalConfig = let
|
||||
template = fromJSON (readFile ./astroid-config-template.json);
|
||||
astroidConfig = foldl' recursiveUpdate template [
|
||||
{
|
||||
astroid.notmuch_config = "${config.xdg.configHome}/notmuch/notmuchrc";
|
||||
accounts = mapAttrs (n: accountAttr) astroidAccounts;
|
||||
crypto.gpg.path = "${pkgs.gnupg}/bin/gpg";
|
||||
}
|
||||
cfg.extraConfig
|
||||
cfg.externalEditor
|
||||
];
|
||||
in astroidConfig;
|
||||
|
||||
in {
|
||||
options = {
|
||||
programs.astroid = {
|
||||
enable = mkEnableOption "Astroid";
|
||||
|
||||
pollScript = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "mbsync gmail";
|
||||
description = ''
|
||||
Script to run to fetch/update mails.
|
||||
'';
|
||||
};
|
||||
|
||||
externalEditor = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
# Converts it into JSON that can be merged into the configuration.
|
||||
apply = cmd:
|
||||
optionalAttrs (cmd != null) {
|
||||
editor = {
|
||||
"external_editor" = "true";
|
||||
"cmd" = cmd;
|
||||
};
|
||||
};
|
||||
example =
|
||||
"nvim-qt -- -c 'set ft=mail' '+set fileencoding=utf-8' '+set ff=unix' '+set enc=utf-8' '+set fo+=w' %1";
|
||||
description = ''
|
||||
You can use <code>%1</code>, <code>%2</code>, and
|
||||
<code>%3</code> to refer respectively to:
|
||||
<orderedlist numeration="arabic">
|
||||
<listitem><para>file name</para></listitem>
|
||||
<listitem><para>server name</para></listitem>
|
||||
<listitem><para>socket ID</para></listitem>
|
||||
</orderedlist>
|
||||
See <link xlink:href='https://github.com/astroidmail/astroid/wiki/Customizing-editor' />.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = jsonFormat.type;
|
||||
default = { };
|
||||
example = literalExample ''
|
||||
{
|
||||
poll.interval = 0;
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
JSON config that will override the default Astroid configuration.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
accounts.email.accounts = mkOption {
|
||||
type = with types; attrsOf (submodule (import ./astroid-accounts.nix));
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
home.packages = [ pkgs.astroid ];
|
||||
|
||||
xdg.configFile."astroid/config".source =
|
||||
jsonFormat.generate "astroid-config" finalConfig;
|
||||
|
||||
xdg.configFile."astroid/poll.sh" = {
|
||||
executable = true;
|
||||
text = ''
|
||||
# Generated by Home Manager
|
||||
|
||||
${cfg.pollScript}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
56
modules/programs/autojump.nix
Normal file
56
modules/programs/autojump.nix
Normal file
@@ -0,0 +1,56 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.programs.autojump;
|
||||
package = pkgs.autojump;
|
||||
|
||||
in {
|
||||
meta.maintainers = [ maintainers.evanjs ];
|
||||
|
||||
options.programs.autojump = {
|
||||
enable = mkEnableOption "autojump";
|
||||
|
||||
enableBashIntegration = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Whether to enable Bash integration.
|
||||
'';
|
||||
};
|
||||
|
||||
enableZshIntegration = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Whether to enable Zsh integration.
|
||||
'';
|
||||
};
|
||||
|
||||
enableFishIntegration = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Whether to enable Fish integration.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
home.packages = [ package ];
|
||||
|
||||
programs.bash.initExtra = mkIf cfg.enableBashIntegration (mkBefore ''
|
||||
. ${package}/share/autojump/autojump.bash
|
||||
'');
|
||||
|
||||
programs.zsh.initExtra = mkIf cfg.enableZshIntegration ''
|
||||
. ${package}/share/autojump/autojump.zsh
|
||||
'';
|
||||
|
||||
programs.fish.promptInit = mkIf cfg.enableFishIntegration ''
|
||||
. ${package}/share/autojump/autojump.fish
|
||||
'';
|
||||
};
|
||||
}
|
||||
364
modules/programs/autorandr.nix
Normal file
364
modules/programs/autorandr.nix
Normal file
@@ -0,0 +1,364 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.programs.autorandr;
|
||||
|
||||
matrixOf = n: m: elemType:
|
||||
mkOptionType rec {
|
||||
name = "matrixOf";
|
||||
description =
|
||||
"${toString n}×${toString m} matrix of ${elemType.description}s";
|
||||
check = xss:
|
||||
let listOfSize = l: xs: isList xs && length xs == l;
|
||||
in listOfSize n xss
|
||||
&& all (xs: listOfSize m xs && all elemType.check xs) xss;
|
||||
merge = mergeOneOption;
|
||||
getSubOptions = prefix: elemType.getSubOptions (prefix ++ [ "*" "*" ]);
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = mod: matrixOf n m (elemType.substSubModules mod);
|
||||
functor = (defaultFunctor name) // { wrapped = elemType; };
|
||||
};
|
||||
|
||||
profileModule = types.submodule {
|
||||
options = {
|
||||
fingerprint = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
description = ''
|
||||
Output name to EDID mapping.
|
||||
Use <code>autorandr --fingerprint</code> to get current setup values.
|
||||
'';
|
||||
default = { };
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
type = types.attrsOf configModule;
|
||||
description = "Per output profile configuration.";
|
||||
default = { };
|
||||
};
|
||||
|
||||
hooks = mkOption {
|
||||
type = profileHooksModule;
|
||||
description = "Profile hook scripts.";
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
configModule = types.submodule {
|
||||
options = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
description = "Whether to enable the output.";
|
||||
default = true;
|
||||
};
|
||||
|
||||
crtc = mkOption {
|
||||
type = types.nullOr types.ints.unsigned;
|
||||
description = "Output video display controller.";
|
||||
default = null;
|
||||
example = 0;
|
||||
};
|
||||
|
||||
primary = mkOption {
|
||||
type = types.bool;
|
||||
description = "Whether output should be marked as primary";
|
||||
default = false;
|
||||
};
|
||||
|
||||
position = mkOption {
|
||||
type = types.str;
|
||||
description = "Output position";
|
||||
default = "";
|
||||
example = "5760x0";
|
||||
};
|
||||
|
||||
mode = mkOption {
|
||||
type = types.str;
|
||||
description = "Output resolution.";
|
||||
default = "";
|
||||
example = "3840x2160";
|
||||
};
|
||||
|
||||
rate = mkOption {
|
||||
type = types.str;
|
||||
description = "Output framerate.";
|
||||
default = "";
|
||||
example = "60.00";
|
||||
};
|
||||
|
||||
gamma = mkOption {
|
||||
type = types.str;
|
||||
description = "Output gamma configuration.";
|
||||
default = "";
|
||||
example = "1.0:0.909:0.833";
|
||||
};
|
||||
|
||||
rotate = mkOption {
|
||||
type = types.nullOr (types.enum [ "normal" "left" "right" "inverted" ]);
|
||||
description = "Output rotate configuration.";
|
||||
default = null;
|
||||
example = "left";
|
||||
};
|
||||
|
||||
transform = mkOption {
|
||||
type = types.nullOr (matrixOf 3 3 types.float);
|
||||
default = null;
|
||||
example = literalExample ''
|
||||
[
|
||||
[ 0.6 0.0 0.0 ]
|
||||
[ 0.0 0.6 0.0 ]
|
||||
[ 0.0 0.0 1.0 ]
|
||||
]
|
||||
'';
|
||||
description = ''
|
||||
Refer to
|
||||
<citerefentry>
|
||||
<refentrytitle>xrandr</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry>
|
||||
for the documentation of the transform matrix.
|
||||
'';
|
||||
};
|
||||
|
||||
dpi = mkOption {
|
||||
type = types.nullOr types.ints.positive;
|
||||
description = "Output DPI configuration.";
|
||||
default = null;
|
||||
example = 96;
|
||||
};
|
||||
|
||||
scale = mkOption {
|
||||
type = types.nullOr (types.submodule {
|
||||
options = {
|
||||
method = mkOption {
|
||||
type = types.enum [ "factor" "pixel" ];
|
||||
description = "Output scaling method.";
|
||||
default = "factor";
|
||||
example = "pixel";
|
||||
};
|
||||
|
||||
x = mkOption {
|
||||
type = types.either types.float types.ints.positive;
|
||||
description = "Horizontal scaling factor/pixels.";
|
||||
};
|
||||
|
||||
y = mkOption {
|
||||
type = types.either types.float types.ints.positive;
|
||||
description = "Vertical scaling factor/pixels.";
|
||||
};
|
||||
};
|
||||
});
|
||||
description = ''
|
||||
Output scale configuration.
|
||||
</para><para>
|
||||
Either configure by pixels or a scaling factor. When using pixel method the
|
||||
<citerefentry>
|
||||
<refentrytitle>xrandr</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry>
|
||||
option
|
||||
<parameter class="command">--scale-from</parameter>
|
||||
will be used; when using factor method the option
|
||||
<parameter class="command">--scale</parameter>
|
||||
will be used.
|
||||
</para><para>
|
||||
This option is a shortcut version of the transform option and they are mutually
|
||||
exclusive.
|
||||
'';
|
||||
default = null;
|
||||
example = literalExample ''
|
||||
{
|
||||
x = 1.25;
|
||||
y = 1.25;
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
hookType = types.lines;
|
||||
|
||||
globalHooksModule = types.submodule {
|
||||
options = {
|
||||
postswitch = mkOption {
|
||||
type = types.attrsOf hookType;
|
||||
description = "Postswitch hook executed after mode switch.";
|
||||
default = { };
|
||||
};
|
||||
|
||||
preswitch = mkOption {
|
||||
type = types.attrsOf hookType;
|
||||
description = "Preswitch hook executed before mode switch.";
|
||||
default = { };
|
||||
};
|
||||
|
||||
predetect = mkOption {
|
||||
type = types.attrsOf hookType;
|
||||
description = ''
|
||||
Predetect hook executed before autorandr attempts to run xrandr.
|
||||
'';
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
profileHooksModule = types.submodule {
|
||||
options = {
|
||||
postswitch = mkOption {
|
||||
type = hookType;
|
||||
description = "Postswitch hook executed after mode switch.";
|
||||
default = "";
|
||||
};
|
||||
|
||||
preswitch = mkOption {
|
||||
type = hookType;
|
||||
description = "Preswitch hook executed before mode switch.";
|
||||
default = "";
|
||||
};
|
||||
|
||||
predetect = mkOption {
|
||||
type = hookType;
|
||||
description = ''
|
||||
Predetect hook executed before autorandr attempts to run xrandr.
|
||||
'';
|
||||
default = "";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
hookToFile = folder: name: hook:
|
||||
nameValuePair "autorandr/${folder}/${name}" {
|
||||
source = "${pkgs.writeShellScriptBin "hook" hook}/bin/hook";
|
||||
};
|
||||
profileToFiles = name: profile:
|
||||
with profile;
|
||||
mkMerge ([
|
||||
{
|
||||
"autorandr/${name}/setup".text = concatStringsSep "\n"
|
||||
(mapAttrsToList fingerprintToString fingerprint);
|
||||
"autorandr/${name}/config".text =
|
||||
concatStringsSep "\n" (mapAttrsToList configToString profile.config);
|
||||
}
|
||||
(mkIf (hooks.postswitch != "")
|
||||
(listToAttrs [ (hookToFile name "postswitch" hooks.postswitch) ]))
|
||||
(mkIf (hooks.preswitch != "")
|
||||
(listToAttrs [ (hookToFile name "preswitch" hooks.preswitch) ]))
|
||||
(mkIf (hooks.predetect != "")
|
||||
(listToAttrs [ (hookToFile name "predetect" hooks.predetect) ]))
|
||||
]);
|
||||
fingerprintToString = name: edid: "${name} ${edid}";
|
||||
configToString = name: config:
|
||||
if config.enable then
|
||||
concatStringsSep "\n" ([ "output ${name}" ]
|
||||
++ optional (config.position != "") "pos ${config.position}"
|
||||
++ optional (config.crtc != null) "crtc ${toString config.crtc}"
|
||||
++ optional config.primary "primary"
|
||||
++ optional (config.dpi != null) "dpi ${toString config.dpi}"
|
||||
++ optional (config.gamma != "") "gamma ${config.gamma}"
|
||||
++ optional (config.mode != "") "mode ${config.mode}"
|
||||
++ optional (config.rate != "") "rate ${config.rate}"
|
||||
++ optional (config.rotate != null) "rotate ${config.rotate}"
|
||||
++ optional (config.transform != null) ("transform "
|
||||
+ concatMapStringsSep "," toString (flatten config.transform))
|
||||
++ optional (config.scale != null)
|
||||
((if config.scale.method == "factor" then "scale" else "scale-from")
|
||||
+ " ${toString config.scale.x}x${toString config.scale.y}"))
|
||||
else ''
|
||||
output ${name}
|
||||
off
|
||||
'';
|
||||
|
||||
in {
|
||||
options = {
|
||||
programs.autorandr = {
|
||||
enable = mkEnableOption "Autorandr";
|
||||
|
||||
hooks = mkOption {
|
||||
type = globalHooksModule;
|
||||
description = "Global hook scripts";
|
||||
default = { };
|
||||
example = literalExample ''
|
||||
{
|
||||
postswitch = {
|
||||
"notify-i3" = "''${pkgs.i3}/bin/i3-msg restart";
|
||||
"change-background" = readFile ./change-background.sh;
|
||||
"change-dpi" = '''
|
||||
case "$AUTORANDR_CURRENT_PROFILE" in
|
||||
default)
|
||||
DPI=120
|
||||
;;
|
||||
home)
|
||||
DPI=192
|
||||
;;
|
||||
work)
|
||||
DPI=144
|
||||
;;
|
||||
*)
|
||||
echo "Unknown profle: $AUTORANDR_CURRENT_PROFILE"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
echo "Xft.dpi: $DPI" | ''${pkgs.xorg.xrdb}/bin/xrdb -merge
|
||||
'''
|
||||
};
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
profiles = mkOption {
|
||||
type = types.attrsOf profileModule;
|
||||
description = "Autorandr profiles specification.";
|
||||
default = { };
|
||||
example = literalExample ''
|
||||
{
|
||||
"work" = {
|
||||
fingerprint = {
|
||||
eDP1 = "<EDID>";
|
||||
DP1 = "<EDID>";
|
||||
};
|
||||
config = {
|
||||
eDP1.enable = false;
|
||||
DP1 = {
|
||||
enable = true;
|
||||
crtc = 0;
|
||||
primary = true;
|
||||
position = "0x0";
|
||||
mode = "3840x2160";
|
||||
gamma = "1.0:0.909:0.833";
|
||||
rate = "60.00";
|
||||
rotate = "left";
|
||||
};
|
||||
};
|
||||
hooks.postswitch = readFile ./work-postswitch.sh;
|
||||
};
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = flatten (mapAttrsToList (profile:
|
||||
{ config, ... }:
|
||||
mapAttrsToList (output: opts: {
|
||||
assertion = opts.scale == null || opts.transform == null;
|
||||
message = ''
|
||||
Cannot use the profile output options 'scale' and 'transform' simultaneously.
|
||||
Check configuration for: programs.autorandr.profiles.${profile}.config.${output}
|
||||
'';
|
||||
}) config) cfg.profiles);
|
||||
|
||||
home.packages = [ pkgs.autorandr ];
|
||||
xdg.configFile = mkMerge ([
|
||||
(mapAttrs' (hookToFile "postswitch.d") cfg.hooks.postswitch)
|
||||
(mapAttrs' (hookToFile "preswitch.d") cfg.hooks.preswitch)
|
||||
(mapAttrs' (hookToFile "predetect.d") cfg.hooks.predetect)
|
||||
(mkMerge (mapAttrsToList profileToFiles cfg.profiles))
|
||||
]);
|
||||
};
|
||||
|
||||
meta.maintainers = [ maintainers.uvnikita ];
|
||||
}
|
||||
@@ -9,6 +9,16 @@ let
|
||||
in
|
||||
|
||||
{
|
||||
meta.maintainers = [ maintainers.rycee ];
|
||||
|
||||
imports = [
|
||||
(mkRenamedOptionModule [ "programs" "bash" "enableAutojump" ] [
|
||||
"programs"
|
||||
"autojump"
|
||||
"enable"
|
||||
])
|
||||
];
|
||||
|
||||
options = {
|
||||
programs.bash = {
|
||||
enable = mkEnableOption "GNU Bourne-Again SHell";
|
||||
@@ -19,6 +29,12 @@ in
|
||||
description = "Number of history lines to keep in memory.";
|
||||
};
|
||||
|
||||
historyFile = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Location of the bash history file.";
|
||||
};
|
||||
|
||||
historyFileSize = mkOption {
|
||||
type = types.int;
|
||||
default = 100000;
|
||||
@@ -62,33 +78,64 @@ in
|
||||
description = "Shell options to set.";
|
||||
};
|
||||
|
||||
shellAliases = mkOption {
|
||||
sessionVariables = mkOption {
|
||||
default = {};
|
||||
example = { ll = "ls -l"; ".." = "cd .."; };
|
||||
description = ''
|
||||
An attribute set that maps aliases (the top level attribute names in
|
||||
this option) to command strings or directly to build outputs. The
|
||||
aliases are added to all users' shells.
|
||||
'';
|
||||
type = types.attrs;
|
||||
example = { MAILCHECK = 30; };
|
||||
description = ''
|
||||
Environment variables that will be set for the Bash session.
|
||||
'';
|
||||
};
|
||||
|
||||
enableAutojump = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = "Enable the autojump navigation tool.";
|
||||
shellAliases = mkOption {
|
||||
default = {};
|
||||
type = types.attrsOf types.str;
|
||||
example = literalExample ''
|
||||
{
|
||||
ll = "ls -l";
|
||||
".." = "cd ..";
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
An attribute set that maps aliases (the top level attribute names in
|
||||
this option) to command strings or directly to build outputs.
|
||||
'';
|
||||
};
|
||||
|
||||
profileExtra = mkOption {
|
||||
default = "";
|
||||
type = types.lines;
|
||||
description = "Extra commands that should be added to .profile.";
|
||||
description = ''
|
||||
Extra commands that should be run when initializing a login
|
||||
shell.
|
||||
'';
|
||||
};
|
||||
|
||||
initExtra = mkOption {
|
||||
default = "";
|
||||
type = types.lines;
|
||||
description = "Extra commands that should be added to .bashrc.";
|
||||
description = ''
|
||||
Extra commands that should be run when initializing an
|
||||
interactive shell.
|
||||
'';
|
||||
};
|
||||
|
||||
bashrcExtra = mkOption {
|
||||
default = "";
|
||||
type = types.lines;
|
||||
description = ''
|
||||
Extra commands that should be placed in <filename>~/.bashrc</filename>.
|
||||
Note that these commands will be run even in non-interactive shells.
|
||||
'';
|
||||
};
|
||||
|
||||
logoutExtra = mkOption {
|
||||
default = "";
|
||||
type = types.lines;
|
||||
description = ''
|
||||
Extra commands that should be run when logging out of an
|
||||
interactive shell.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -96,23 +143,31 @@ in
|
||||
config = (
|
||||
let
|
||||
aliasesStr = concatStringsSep "\n" (
|
||||
mapAttrsToList (k: v: "alias ${k}='${v}'") cfg.shellAliases
|
||||
mapAttrsToList (k: v: "alias ${k}=${escapeShellArg v}") cfg.shellAliases
|
||||
);
|
||||
|
||||
shoptsStr = concatStringsSep "\n" (
|
||||
map (v: "shopt -s ${v}") cfg.shellOptions
|
||||
);
|
||||
|
||||
export = n: v: "export ${n}=\"${toString v}\"";
|
||||
exportIfNonNull = n: v: optionalString (v != null) (export n v);
|
||||
exportIfNonEmpty = n: v: optionalString (v != "") (export n v);
|
||||
sessionVarsStr = config.lib.shell.exportAll cfg.sessionVariables;
|
||||
|
||||
histControlStr = concatStringsSep ":" cfg.historyControl;
|
||||
histIgnoreStr = concatStringsSep ":" cfg.historyIgnore;
|
||||
|
||||
envVarsStr = concatStringsSep "\n" (
|
||||
mapAttrsToList export config.home.sessionVariables
|
||||
);
|
||||
historyControlStr =
|
||||
concatStringsSep "\n" (mapAttrsToList (n: v: "${n}=${v}") (
|
||||
{
|
||||
HISTFILESIZE = toString cfg.historyFileSize;
|
||||
HISTSIZE = toString cfg.historySize;
|
||||
}
|
||||
// optionalAttrs (cfg.historyFile != null) {
|
||||
HISTFILE = "\"${cfg.historyFile}\"";
|
||||
}
|
||||
// optionalAttrs (cfg.historyControl != []) {
|
||||
HISTCONTROL = concatStringsSep ":" cfg.historyControl;
|
||||
}
|
||||
// optionalAttrs (cfg.historyIgnore != []) {
|
||||
HISTIGNORE = concatStringsSep ":" cfg.historyIgnore;
|
||||
}
|
||||
));
|
||||
in mkIf cfg.enable {
|
||||
home.file.".bash_profile".text = ''
|
||||
# -*- mode: sh -*-
|
||||
@@ -127,8 +182,9 @@ in
|
||||
home.file.".profile".text = ''
|
||||
# -*- mode: sh -*-
|
||||
|
||||
${optionalString (config.home.sessionVariableSetter == "bash")
|
||||
envVarsStr}
|
||||
. "${config.home.profileDirectory}/etc/profile.d/hm-session-vars.sh"
|
||||
|
||||
${sessionVarsStr}
|
||||
|
||||
${cfg.profileExtra}
|
||||
'';
|
||||
@@ -136,26 +192,27 @@ in
|
||||
home.file.".bashrc".text = ''
|
||||
# -*- mode: sh -*-
|
||||
|
||||
# Skip if not running interactively.
|
||||
[ -z "$PS1" ] && return
|
||||
${cfg.bashrcExtra}
|
||||
|
||||
${export "HISTSIZE" cfg.historySize}
|
||||
${export "HISTFILESIZE" cfg.historyFileSize}
|
||||
${exportIfNonEmpty "HISTCONTROL" histControlStr}
|
||||
${exportIfNonEmpty "HISTIGNORE" histIgnoreStr}
|
||||
# Commands that should be applied only for interactive shells.
|
||||
[[ $- == *i* ]] || return
|
||||
|
||||
${historyControlStr}
|
||||
|
||||
${shoptsStr}
|
||||
|
||||
${aliasesStr}
|
||||
|
||||
${cfg.initExtra}
|
||||
|
||||
${optionalString cfg.enableAutojump
|
||||
". ${pkgs.autojump}/share/autojump/autojump.bash"}
|
||||
'';
|
||||
|
||||
home.packages =
|
||||
optional (cfg.enableAutojump) pkgs.autojump;
|
||||
home.file.".bash_logout" = mkIf (cfg.logoutExtra != "") {
|
||||
text = ''
|
||||
# -*- mode: sh -*-
|
||||
|
||||
${cfg.logoutExtra}
|
||||
'';
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
58
modules/programs/bat.nix
Normal file
58
modules/programs/bat.nix
Normal file
@@ -0,0 +1,58 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.programs.bat;
|
||||
|
||||
in {
|
||||
meta.maintainers = [ maintainers.marsam ];
|
||||
|
||||
options.programs.bat = {
|
||||
enable = mkEnableOption "bat, a cat clone with wings";
|
||||
|
||||
config = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = { };
|
||||
example = {
|
||||
theme = "TwoDark";
|
||||
pager = "less -FR";
|
||||
};
|
||||
description = ''
|
||||
Bat configuration.
|
||||
'';
|
||||
};
|
||||
|
||||
themes = mkOption {
|
||||
type = types.attrsOf types.lines;
|
||||
default = { };
|
||||
example = literalExample ''
|
||||
{
|
||||
dracula = builtins.readFile (pkgs.fetchFromGitHub {
|
||||
owner = "dracula";
|
||||
repo = "sublime"; # Bat uses sublime syntax for its themes
|
||||
rev = "26c57ec282abcaa76e57e055f38432bd827ac34e";
|
||||
sha256 = "019hfl4zbn4vm4154hh3bwk6hm7bdxbr1hdww83nabxwjn99ndhv";
|
||||
} + "/Dracula.tmTheme");
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
Additional themes to provide.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
home.packages = [ pkgs.bat ];
|
||||
|
||||
xdg.configFile = mkMerge ([{
|
||||
"bat/config" = mkIf (cfg.config != { }) {
|
||||
text = concatStringsSep "\n"
|
||||
(mapAttrsToList (n: v: ''--${n}="${v}"'') cfg.config);
|
||||
};
|
||||
}] ++ flip mapAttrsToList cfg.themes
|
||||
(name: body: { "bat/themes/${name}.tmTheme" = { text = body; }; }));
|
||||
};
|
||||
}
|
||||
@@ -6,14 +6,43 @@ let
|
||||
|
||||
cfg = config.programs.beets;
|
||||
|
||||
in
|
||||
yamlFormat = pkgs.formats.yaml { };
|
||||
|
||||
in {
|
||||
meta.maintainers = [ maintainers.rycee ];
|
||||
|
||||
{
|
||||
options = {
|
||||
programs.beets = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = if versionAtLeast config.home.stateVersion "19.03" then
|
||||
false
|
||||
else
|
||||
cfg.settings != { };
|
||||
defaultText = "false";
|
||||
description = ''
|
||||
Whether to enable the beets music library manager. This
|
||||
defaults to <literal>false</literal> for state
|
||||
version ≥ 19.03. For earlier versions beets is enabled if
|
||||
<option>programs.beets.settings</option> is non-empty.
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.beets;
|
||||
defaultText = literalExample "pkgs.beets";
|
||||
example =
|
||||
literalExample "(pkgs.beets.override { enableCheck = true; })";
|
||||
description = ''
|
||||
The <literal>beets</literal> package to use.
|
||||
Can be used to specify extensions.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
type = yamlFormat.type;
|
||||
default = { };
|
||||
description = ''
|
||||
Configuration written to
|
||||
<filename>~/.config/beets/config.yaml</filename>
|
||||
@@ -22,10 +51,10 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf (cfg.settings != {}) {
|
||||
home.packages = [ pkgs.beets ];
|
||||
config = mkIf cfg.enable {
|
||||
home.packages = [ cfg.package ];
|
||||
|
||||
home.file.".config/beets/config.yaml".text =
|
||||
builtins.toJSON config.programs.beets.settings;
|
||||
xdg.configFile."beets/config.yaml".source =
|
||||
yamlFormat.generate "beets-config" cfg.settings;
|
||||
};
|
||||
}
|
||||
|
||||
273
modules/programs/broot.nix
Normal file
273
modules/programs/broot.nix
Normal file
@@ -0,0 +1,273 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.programs.broot;
|
||||
|
||||
tomlFormat = pkgs.formats.toml { };
|
||||
|
||||
brootConf = {
|
||||
verbs = cfg.verbs;
|
||||
skin = cfg.skin;
|
||||
};
|
||||
|
||||
in {
|
||||
meta.maintainers = [ maintainers.aheaume ];
|
||||
|
||||
options.programs.broot = {
|
||||
enable = mkEnableOption "Broot, a better way to navigate directories";
|
||||
|
||||
enableBashIntegration = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Whether to enable Bash integration.
|
||||
'';
|
||||
};
|
||||
|
||||
enableZshIntegration = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Whether to enable Zsh integration.
|
||||
'';
|
||||
};
|
||||
|
||||
enableFishIntegration = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Whether to enable Fish integration.
|
||||
'';
|
||||
};
|
||||
|
||||
verbs = mkOption {
|
||||
type = with types; listOf (attrsOf (either bool str));
|
||||
default = [
|
||||
{
|
||||
invocation = "p";
|
||||
execution = ":parent";
|
||||
}
|
||||
{
|
||||
invocation = "edit";
|
||||
shortcut = "e";
|
||||
execution = "$EDITOR {file}";
|
||||
}
|
||||
{
|
||||
invocation = "create {subpath}";
|
||||
execution = "$EDITOR {directory}/{subpath}";
|
||||
}
|
||||
{
|
||||
invocation = "view";
|
||||
execution = "less {file}";
|
||||
}
|
||||
];
|
||||
example = literalExample ''
|
||||
[
|
||||
{ invocation = "p"; execution = ":parent"; }
|
||||
{ invocation = "edit"; shortcut = "e"; execution = "$EDITOR {file}" ; }
|
||||
{ invocation = "create {subpath}"; execution = "$EDITOR {directory}/{subpath}"; }
|
||||
{ invocation = "view"; execution = "less {file}"; }
|
||||
{
|
||||
invocation = "blop {name}\\.{type}";
|
||||
execution = "/bin/mkdir {parent}/{type} && /usr/bin/nvim {parent}/{type}/{name}.{type}";
|
||||
from_shell = true;
|
||||
}
|
||||
]
|
||||
'';
|
||||
description = ''
|
||||
Define new verbs. For more information, see
|
||||
<link xlink:href="https://dystroy.org/broot/documentation/configuration/#verb-definition-attributes"/>.
|
||||
</para><para>
|
||||
The possible attributes are:
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><literal>invocation</literal> (optional)</term>
|
||||
<listitem><para>how the verb is called by the user, with placeholders for arguments</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><literal>execution</literal> (mandatory)</term>
|
||||
<listitem><para>how the verb is executed</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><literal>key</literal> (optional)</term>
|
||||
<listitem><para>a keyboard key triggering execution</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><literal>shortcut</literal> (optional)</term>
|
||||
<listitem><para>an alternate way to call the verb (without
|
||||
the arguments part)</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><literal>leave_broot</literal> (optional)</term>
|
||||
<listitem><para>whether to quit broot on execution
|
||||
(default: <literal>true</literal>)</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><literal>from_shell</literal> (optional)</term>
|
||||
<listitem><para>whether the verb must be executed from the
|
||||
parent shell (default:
|
||||
<literal>false</literal>)</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.broot;
|
||||
defaultText = literalExample "pkgs.broot";
|
||||
description = "Package providing broot";
|
||||
};
|
||||
|
||||
skin = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = { };
|
||||
example = literalExample ''
|
||||
{
|
||||
status_normal_fg = "grayscale(18)";
|
||||
status_normal_bg = "grayscale(3)";
|
||||
status_error_fg = "red";
|
||||
status_error_bg = "yellow";
|
||||
tree_fg = "red";
|
||||
selected_line_bg = "grayscale(7)";
|
||||
permissions_fg = "grayscale(12)";
|
||||
size_bar_full_bg = "red";
|
||||
size_bar_void_bg = "black";
|
||||
directory_fg = "lightyellow";
|
||||
input_fg = "cyan";
|
||||
flag_value_fg = "lightyellow";
|
||||
table_border_fg = "red";
|
||||
code_fg = "lightyellow";
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
Color configuration.
|
||||
</para><para>
|
||||
Complete list of keys (expected to change before the v1 of broot):
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para><literal>char_match</literal></para></listitem>
|
||||
<listitem><para><literal>code</literal></para></listitem>
|
||||
<listitem><para><literal>directory</literal></para></listitem>
|
||||
<listitem><para><literal>exe</literal></para></listitem>
|
||||
<listitem><para><literal>file</literal></para></listitem>
|
||||
<listitem><para><literal>file_error</literal></para></listitem>
|
||||
<listitem><para><literal>flag_label</literal></para></listitem>
|
||||
<listitem><para><literal>flag_value</literal></para></listitem>
|
||||
<listitem><para><literal>input</literal></para></listitem>
|
||||
<listitem><para><literal>link</literal></para></listitem>
|
||||
<listitem><para><literal>permissions</literal></para></listitem>
|
||||
<listitem><para><literal>selected_line</literal></para></listitem>
|
||||
<listitem><para><literal>size_bar_full</literal></para></listitem>
|
||||
<listitem><para><literal>size_bar_void</literal></para></listitem>
|
||||
<listitem><para><literal>size_text</literal></para></listitem>
|
||||
<listitem><para><literal>spinner</literal></para></listitem>
|
||||
<listitem><para><literal>status_error</literal></para></listitem>
|
||||
<listitem><para><literal>status_normal</literal></para></listitem>
|
||||
<listitem><para><literal>table_border</literal></para></listitem>
|
||||
<listitem><para><literal>tree</literal></para></listitem>
|
||||
<listitem><para><literal>unlisted</literal></para></listitem>
|
||||
</itemizedlist></para>
|
||||
|
||||
<para>
|
||||
Add <literal>_fg</literal> for a foreground color and
|
||||
<literal>_bg</literal> for a background colors.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
home.packages = [ cfg.package ];
|
||||
|
||||
xdg.configFile."broot/conf.toml".source =
|
||||
tomlFormat.generate "broot-config" brootConf;
|
||||
|
||||
# Dummy file to prevent broot from trying to reinstall itself
|
||||
xdg.configFile."broot/launcher/installed-v1".text = "";
|
||||
|
||||
programs.bash.initExtra = mkIf cfg.enableBashIntegration (
|
||||
# Using mkAfter to make it more likely to appear after other
|
||||
# manipulations of the prompt.
|
||||
mkAfter ''
|
||||
# This script was automatically generated by the broot function
|
||||
# More information can be found in https://github.com/Canop/broot
|
||||
# This function starts broot and executes the command
|
||||
# it produces, if any.
|
||||
# It's needed because some shell commands, like `cd`,
|
||||
# have no useful effect if executed in a subshell.
|
||||
function br {
|
||||
f=$(mktemp)
|
||||
(
|
||||
set +e
|
||||
broot --outcmd "$f" "$@"
|
||||
code=$?
|
||||
if [ "$code" != 0 ]; then
|
||||
rm -f "$f"
|
||||
exit "$code"
|
||||
fi
|
||||
)
|
||||
code=$?
|
||||
if [ "$code" != 0 ]; then
|
||||
return "$code"
|
||||
fi
|
||||
d=$(cat "$f")
|
||||
rm -f "$f"
|
||||
eval "$d"
|
||||
}
|
||||
'');
|
||||
|
||||
programs.zsh.initExtra = mkIf cfg.enableZshIntegration ''
|
||||
# This script was automatically generated by the broot function
|
||||
# More information can be found in https://github.com/Canop/broot
|
||||
# This function starts broot and executes the command
|
||||
# it produces, if any.
|
||||
# It's needed because some shell commands, like `cd`,
|
||||
# have no useful effect if executed in a subshell.
|
||||
function br {
|
||||
f=$(mktemp)
|
||||
(
|
||||
set +e
|
||||
broot --outcmd "$f" "$@"
|
||||
code=$?
|
||||
if [ "$code" != 0 ]; then
|
||||
rm -f "$f"
|
||||
exit "$code"
|
||||
fi
|
||||
)
|
||||
code=$?
|
||||
if [ "$code" != 0 ]; then
|
||||
return "$code"
|
||||
fi
|
||||
d=$(cat "$f")
|
||||
rm -f "$f"
|
||||
eval "$d"
|
||||
}
|
||||
'';
|
||||
|
||||
programs.fish.shellInit = mkIf cfg.enableFishIntegration ''
|
||||
# This script was automatically generated by the broot function
|
||||
# More information can be found in https://github.com/Canop/broot
|
||||
# This function starts broot and executes the command
|
||||
# it produces, if any.
|
||||
# It's needed because some shell commands, like `cd`,
|
||||
# have no useful effect if executed in a subshell.
|
||||
function br
|
||||
set f (mktemp)
|
||||
broot --outcmd $f $argv
|
||||
if test $status -ne 0
|
||||
rm -f "$f"
|
||||
return "$code"
|
||||
end
|
||||
set d (cat "$f")
|
||||
rm -f "$f"
|
||||
eval "$d"
|
||||
end
|
||||
'';
|
||||
};
|
||||
}
|
||||
76
modules/programs/browserpass.nix
Normal file
76
modules/programs/browserpass.nix
Normal file
@@ -0,0 +1,76 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let browsers = [ "chrome" "chromium" "firefox" "vivaldi" ];
|
||||
in {
|
||||
options = {
|
||||
programs.browserpass = {
|
||||
enable = mkEnableOption "the browserpass extension host application";
|
||||
|
||||
browsers = mkOption {
|
||||
type = types.listOf (types.enum browsers);
|
||||
default = browsers;
|
||||
example = [ "firefox" ];
|
||||
description = "Which browsers to install browserpass for";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf config.programs.browserpass.enable {
|
||||
home.file = foldl' (a: b: a // b) { } (concatMap (x:
|
||||
with pkgs.stdenv;
|
||||
if x == "chrome" then
|
||||
let
|
||||
dir = if isDarwin then
|
||||
"Library/Application Support/Google/Chrome/NativeMessagingHosts"
|
||||
else
|
||||
".config/google-chrome/NativeMessagingHosts";
|
||||
in [{
|
||||
"${dir}/com.github.browserpass.native.json".source =
|
||||
"${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json";
|
||||
"${dir}/../policies/managed/com.github.browserpass.native.json".source =
|
||||
"${pkgs.browserpass}/lib/browserpass/policies/chromium/com.github.browserpass.native.json";
|
||||
}]
|
||||
else if x == "chromium" then
|
||||
let
|
||||
dir = if isDarwin then
|
||||
"Library/Application Support/Chromium/NativeMessagingHosts"
|
||||
else
|
||||
".config/chromium/NativeMessagingHosts";
|
||||
in [
|
||||
{
|
||||
"${dir}/com.github.browserpass.native.json".source =
|
||||
"${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json";
|
||||
}
|
||||
{
|
||||
"${dir}/../policies/managed/com.github.browserpass.native.json".source =
|
||||
"${pkgs.browserpass}/lib/browserpass/policies/chromium/com.github.browserpass.native.json";
|
||||
}
|
||||
]
|
||||
else if x == "firefox" then
|
||||
let
|
||||
dir = if isDarwin then
|
||||
"Library/Application Support/Mozilla/NativeMessagingHosts"
|
||||
else
|
||||
".mozilla/native-messaging-hosts";
|
||||
in [{
|
||||
"${dir}/com.github.browserpass.native.json".source =
|
||||
"${pkgs.browserpass}/lib/browserpass/hosts/firefox/com.github.browserpass.native.json";
|
||||
}]
|
||||
else if x == "vivaldi" then
|
||||
let
|
||||
dir = if isDarwin then
|
||||
"Library/Application Support/Vivaldi/NativeMessagingHosts"
|
||||
else
|
||||
".config/vivaldi/NativeMessagingHosts";
|
||||
in [{
|
||||
"${dir}/com.github.browserpass.native.json".source =
|
||||
"${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json";
|
||||
"${dir}/../policies/managed/com.github.browserpass.native.json".source =
|
||||
"${pkgs.browserpass}/lib/browserpass/policies/chromium/com.github.browserpass.native.json";
|
||||
}]
|
||||
else
|
||||
throw "unknown browser ${x}") config.programs.browserpass.browsers);
|
||||
};
|
||||
}
|
||||
166
modules/programs/chromium.nix
Normal file
166
modules/programs/chromium.nix
Normal file
@@ -0,0 +1,166 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
browserModule = defaultPkg: name: visible:
|
||||
let
|
||||
browser = (builtins.parseDrvName defaultPkg.name).name;
|
||||
isProprietaryChrome = hasPrefix "Google Chrome" name;
|
||||
in {
|
||||
enable = mkOption {
|
||||
inherit visible;
|
||||
default = false;
|
||||
example = true;
|
||||
description = "Whether to enable ${name}.";
|
||||
type = lib.types.bool;
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
inherit visible;
|
||||
type = types.package;
|
||||
default = defaultPkg;
|
||||
defaultText = literalExample "pkgs.${browser}";
|
||||
description = "The ${name} package to use.";
|
||||
};
|
||||
} // optionalAttrs (!isProprietaryChrome) {
|
||||
# Extensions do not work with Google Chrome
|
||||
# see https://github.com/nix-community/home-manager/issues/1383
|
||||
extensions = mkOption {
|
||||
inherit visible;
|
||||
type = with types;
|
||||
let
|
||||
extensionType = submodule {
|
||||
options = {
|
||||
id = mkOption {
|
||||
type = strMatching "[a-zA-Z]{32}";
|
||||
description = ''
|
||||
The extension's ID from the Chome Web Store url or the unpacked crx.
|
||||
'';
|
||||
default = "";
|
||||
};
|
||||
|
||||
updateUrl = mkOption {
|
||||
type = str;
|
||||
description = ''
|
||||
URL of the extension's update manifest XML file. Linux only.
|
||||
'';
|
||||
default = "https://clients2.google.com/service/update2/crx";
|
||||
visible = pkgs.stdenv.isLinux;
|
||||
readOnly = pkgs.stdenv.isDarwin;
|
||||
};
|
||||
|
||||
crxPath = mkOption {
|
||||
type = nullOr path;
|
||||
description = ''
|
||||
Path to the extension's crx file. Linux only.
|
||||
'';
|
||||
default = null;
|
||||
visible = pkgs.stdenv.isLinux;
|
||||
};
|
||||
|
||||
version = mkOption {
|
||||
type = nullOr str;
|
||||
description = ''
|
||||
The extension's version, required for local installation. Linux only.
|
||||
'';
|
||||
default = null;
|
||||
visible = pkgs.stdenv.isLinux;
|
||||
};
|
||||
};
|
||||
};
|
||||
in listOf (coercedTo str (v: { id = v; }) extensionType);
|
||||
default = [ ];
|
||||
example = literalExample ''
|
||||
[
|
||||
{ id = "cjpalhdlnbpafiamejdnhcphjbkeiagm"; } # ublock origin
|
||||
{
|
||||
id = "dcpihecpambacapedldabdbpakmachpb";
|
||||
updateUrl = "https://raw.githubusercontent.com/iamadamdev/bypass-paywalls-chrome/master/updates.xml";
|
||||
}
|
||||
{
|
||||
id = "aaaaaaaaaabbbbbbbbbbcccccccccc";
|
||||
crxPath = "/home/share/extension.crx";
|
||||
version = "1.0";
|
||||
}
|
||||
]
|
||||
'';
|
||||
description = ''
|
||||
List of ${name} extensions to install.
|
||||
To find the extension ID, check its URL on the
|
||||
<link xlink:href="https://chrome.google.com/webstore/category/extensions">Chrome Web Store</link>.
|
||||
</para><para>
|
||||
To install extensions outside of the Chrome Web Store set
|
||||
<literal>updateUrl</literal> or <literal>crxPath</literal> and
|
||||
<literal>version</literal> as explained in the
|
||||
<link xlink:href="https://developer.chrome.com/docs/extensions/mv2/external_extensions">Chrome
|
||||
documentation</link>.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
browserConfig = cfg:
|
||||
let
|
||||
|
||||
drvName = (builtins.parseDrvName cfg.package.name).name;
|
||||
browser = if drvName == "ungoogled-chromium" then "chromium" else drvName;
|
||||
|
||||
darwinDirs = {
|
||||
chromium = "Chromium";
|
||||
google-chrome = "Google/Chrome";
|
||||
google-chrome-beta = "Google/Chrome Beta";
|
||||
google-chrome-dev = "Google/Chrome Dev";
|
||||
brave = "BraveSoftware/Brave-Browser";
|
||||
};
|
||||
|
||||
configDir = if pkgs.stdenv.isDarwin then
|
||||
"Library/Application Support/${getAttr browser darwinDirs}"
|
||||
else
|
||||
"${config.xdg.configHome}/${browser}";
|
||||
|
||||
extensionJson = ext:
|
||||
assert ext.crxPath != null -> ext.version != null;
|
||||
with builtins; {
|
||||
name = "${configDir}/External Extensions/${ext.id}.json";
|
||||
value.text = toJSON (if ext.crxPath != null then {
|
||||
external_crx = ext.crxPath;
|
||||
external_version = ext.version;
|
||||
} else {
|
||||
external_update_url = ext.updateUrl;
|
||||
});
|
||||
};
|
||||
|
||||
in mkIf cfg.enable {
|
||||
home.packages = [ cfg.package ];
|
||||
home.file = listToAttrs (map extensionJson (cfg.extensions or [ ]));
|
||||
};
|
||||
|
||||
in {
|
||||
# Extensions do not work with the proprietary Google Chrome version
|
||||
# see https://github.com/nix-community/home-manager/issues/1383
|
||||
imports = map (flip mkRemovedOptionModule
|
||||
"The `extensions` option does not work on Google Chrome anymore.") [
|
||||
[ "programs" "google-chrome" "extensions" ]
|
||||
[ "programs" "google-chrome-beta" "extensions" ]
|
||||
[ "programs" "google-chrome-dev" "extensions" ]
|
||||
];
|
||||
|
||||
options.programs = {
|
||||
chromium = browserModule pkgs.chromium "Chromium" true;
|
||||
google-chrome = browserModule pkgs.google-chrome "Google Chrome" false;
|
||||
google-chrome-beta =
|
||||
browserModule pkgs.google-chrome-beta "Google Chrome Beta" false;
|
||||
google-chrome-dev =
|
||||
browserModule pkgs.google-chrome-dev "Google Chrome Dev" false;
|
||||
brave = browserModule pkgs.brave "Brave Browser" false;
|
||||
};
|
||||
|
||||
config = mkMerge [
|
||||
(browserConfig config.programs.chromium)
|
||||
(browserConfig config.programs.google-chrome)
|
||||
(browserConfig config.programs.google-chrome-beta)
|
||||
(browserConfig config.programs.google-chrome-dev)
|
||||
(browserConfig config.programs.brave)
|
||||
];
|
||||
}
|
||||
59
modules/programs/command-not-found/command-not-found.nix
Normal file
59
modules/programs/command-not-found/command-not-found.nix
Normal file
@@ -0,0 +1,59 @@
|
||||
# Adapted from Nixpkgs.
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.programs.command-not-found;
|
||||
commandNotFound = pkgs.substituteAll {
|
||||
name = "command-not-found";
|
||||
dir = "bin";
|
||||
src = ./command-not-found.pl;
|
||||
isExecutable = true;
|
||||
inherit (pkgs) perl;
|
||||
inherit (cfg) dbPath;
|
||||
perlFlags = concatStrings (map (path: "-I ${path}/lib/perl5/site_perl ") [
|
||||
pkgs.perlPackages.DBI
|
||||
pkgs.perlPackages.DBDSQLite
|
||||
pkgs.perlPackages.StringShellQuote
|
||||
]);
|
||||
};
|
||||
|
||||
shInit = commandNotFoundHandlerName: ''
|
||||
# This function is called whenever a command is not found.
|
||||
${commandNotFoundHandlerName}() {
|
||||
local p=${commandNotFound}/bin/command-not-found
|
||||
if [ -x $p -a -f ${cfg.dbPath} ]; then
|
||||
# Run the helper program.
|
||||
$p "$@"
|
||||
else
|
||||
echo "$1: command not found" >&2
|
||||
return 127
|
||||
fi
|
||||
}
|
||||
'';
|
||||
|
||||
in {
|
||||
options.programs.command-not-found = {
|
||||
enable = mkEnableOption "command-not-found hook for interactive shell";
|
||||
|
||||
dbPath = mkOption {
|
||||
default =
|
||||
"/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite";
|
||||
description = ''
|
||||
Absolute path to <filename>programs.sqlite</filename>. By
|
||||
default this file will be provided by your channel
|
||||
(nixexprs.tar.xz).
|
||||
'';
|
||||
type = types.path;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
programs.bash.initExtra = shInit "command_not_found_handle";
|
||||
programs.zsh.initExtra = shInit "command_not_found_handler";
|
||||
|
||||
home.packages = [ commandNotFound ];
|
||||
};
|
||||
}
|
||||
44
modules/programs/command-not-found/command-not-found.pl
Normal file
44
modules/programs/command-not-found/command-not-found.pl
Normal file
@@ -0,0 +1,44 @@
|
||||
#! @perl@/bin/perl -w @perlFlags@
|
||||
|
||||
use strict;
|
||||
use DBI;
|
||||
use DBD::SQLite;
|
||||
use String::ShellQuote;
|
||||
use Config;
|
||||
|
||||
my $program = $ARGV[0];
|
||||
|
||||
my $dbPath = "@dbPath@";
|
||||
|
||||
my $dbh = DBI->connect("dbi:SQLite:dbname=$dbPath", "", "")
|
||||
or die "cannot open database `$dbPath'";
|
||||
$dbh->{RaiseError} = 0;
|
||||
$dbh->{PrintError} = 0;
|
||||
|
||||
my $system = $ENV{"NIX_SYSTEM"} // $Config{myarchname};
|
||||
|
||||
my $res = $dbh->selectall_arrayref(
|
||||
"select package from Programs where system = ? and name = ?",
|
||||
{ Slice => {} }, $system, $program);
|
||||
|
||||
if (!defined $res || scalar @$res == 0) {
|
||||
print STDERR "$program: command not found\n";
|
||||
} elsif (scalar @$res == 1) {
|
||||
my $package = @$res[0]->{package};
|
||||
if ($ENV{"NIX_AUTO_RUN"} // "") {
|
||||
exec("nix-shell", "-p", $package, "--run", shell_quote("exec", @ARGV));
|
||||
} else {
|
||||
print STDERR <<EOF;
|
||||
The program ‘$program’ is currently not installed. You can install it by typing:
|
||||
nix-env -iA nixos.$package
|
||||
EOF
|
||||
}
|
||||
} else {
|
||||
print STDERR <<EOF;
|
||||
The program ‘$program’ is currently not installed. It is provided by
|
||||
several packages. You can install it by typing one of the following:
|
||||
EOF
|
||||
print STDERR " nix-env -iA nixos.$_->{package}\n" foreach @$res;
|
||||
}
|
||||
|
||||
exit 127;
|
||||
223
modules/programs/dircolors.nix
Normal file
223
modules/programs/dircolors.nix
Normal file
@@ -0,0 +1,223 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.programs.dircolors;
|
||||
|
||||
formatLine = n: v: "${n} ${toString v}";
|
||||
in {
|
||||
meta.maintainers = [ hm.maintainers.justinlovinger ];
|
||||
|
||||
options.programs.dircolors = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to manage <filename>.dir_colors</filename>
|
||||
and set <code>LS_COLORS</code>.
|
||||
'';
|
||||
};
|
||||
|
||||
enableBashIntegration = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to enable Bash integration.
|
||||
'';
|
||||
};
|
||||
|
||||
enableFishIntegration = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to enable Fish integration.
|
||||
'';
|
||||
};
|
||||
|
||||
enableZshIntegration = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to enable Zsh integration.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = with types; attrsOf str;
|
||||
default = { };
|
||||
description = ''
|
||||
Options to add to <filename>.dir_colors</filename> file.
|
||||
See <command>dircolors --print-database</command>
|
||||
for options.
|
||||
'';
|
||||
example = literalExample ''
|
||||
{
|
||||
OTHER_WRITABLE = "30;46";
|
||||
".sh" = "01;32";
|
||||
".csh" = "01;32";
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Extra lines added to <filename>.dir_colors</filename> file.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Add default settings from `dircolors --print-database`.
|
||||
programs.dircolors.settings = {
|
||||
RESET = mkDefault "0";
|
||||
DIR = mkDefault "01;34";
|
||||
LINK = mkDefault "01;36";
|
||||
MULTIHARDLINK = mkDefault "00";
|
||||
FIFO = mkDefault "40;33";
|
||||
SOCK = mkDefault "01;35";
|
||||
DOOR = mkDefault "01;35";
|
||||
BLK = mkDefault "40;33;01";
|
||||
CHR = mkDefault "40;33;01";
|
||||
ORPHAN = mkDefault "40;31;01";
|
||||
MISSING = mkDefault "00";
|
||||
SETUID = mkDefault "37;41";
|
||||
SETGID = mkDefault "30;43";
|
||||
CAPABILITY = mkDefault "30;41";
|
||||
STICKY_OTHER_WRITABLE = mkDefault "30;42";
|
||||
OTHER_WRITABLE = mkDefault "34;42";
|
||||
STICKY = mkDefault "37;44";
|
||||
EXEC = mkDefault "01;32";
|
||||
".tar" = mkDefault "01;31";
|
||||
".tgz" = mkDefault "01;31";
|
||||
".arc" = mkDefault "01;31";
|
||||
".arj" = mkDefault "01;31";
|
||||
".taz" = mkDefault "01;31";
|
||||
".lha" = mkDefault "01;31";
|
||||
".lz4" = mkDefault "01;31";
|
||||
".lzh" = mkDefault "01;31";
|
||||
".lzma" = mkDefault "01;31";
|
||||
".tlz" = mkDefault "01;31";
|
||||
".txz" = mkDefault "01;31";
|
||||
".tzo" = mkDefault "01;31";
|
||||
".t7z" = mkDefault "01;31";
|
||||
".zip" = mkDefault "01;31";
|
||||
".z" = mkDefault "01;31";
|
||||
".dz" = mkDefault "01;31";
|
||||
".gz" = mkDefault "01;31";
|
||||
".lrz" = mkDefault "01;31";
|
||||
".lz" = mkDefault "01;31";
|
||||
".lzo" = mkDefault "01;31";
|
||||
".xz" = mkDefault "01;31";
|
||||
".zst" = mkDefault "01;31";
|
||||
".tzst" = mkDefault "01;31";
|
||||
".bz2" = mkDefault "01;31";
|
||||
".bz" = mkDefault "01;31";
|
||||
".tbz" = mkDefault "01;31";
|
||||
".tbz2" = mkDefault "01;31";
|
||||
".tz" = mkDefault "01;31";
|
||||
".deb" = mkDefault "01;31";
|
||||
".rpm" = mkDefault "01;31";
|
||||
".jar" = mkDefault "01;31";
|
||||
".war" = mkDefault "01;31";
|
||||
".ear" = mkDefault "01;31";
|
||||
".sar" = mkDefault "01;31";
|
||||
".rar" = mkDefault "01;31";
|
||||
".alz" = mkDefault "01;31";
|
||||
".ace" = mkDefault "01;31";
|
||||
".zoo" = mkDefault "01;31";
|
||||
".cpio" = mkDefault "01;31";
|
||||
".7z" = mkDefault "01;31";
|
||||
".rz" = mkDefault "01;31";
|
||||
".cab" = mkDefault "01;31";
|
||||
".wim" = mkDefault "01;31";
|
||||
".swm" = mkDefault "01;31";
|
||||
".dwm" = mkDefault "01;31";
|
||||
".esd" = mkDefault "01;31";
|
||||
".jpg" = mkDefault "01;35";
|
||||
".jpeg" = mkDefault "01;35";
|
||||
".mjpg" = mkDefault "01;35";
|
||||
".mjpeg" = mkDefault "01;35";
|
||||
".gif" = mkDefault "01;35";
|
||||
".bmp" = mkDefault "01;35";
|
||||
".pbm" = mkDefault "01;35";
|
||||
".pgm" = mkDefault "01;35";
|
||||
".ppm" = mkDefault "01;35";
|
||||
".tga" = mkDefault "01;35";
|
||||
".xbm" = mkDefault "01;35";
|
||||
".xpm" = mkDefault "01;35";
|
||||
".tif" = mkDefault "01;35";
|
||||
".tiff" = mkDefault "01;35";
|
||||
".png" = mkDefault "01;35";
|
||||
".svg" = mkDefault "01;35";
|
||||
".svgz" = mkDefault "01;35";
|
||||
".mng" = mkDefault "01;35";
|
||||
".pcx" = mkDefault "01;35";
|
||||
".mov" = mkDefault "01;35";
|
||||
".mpg" = mkDefault "01;35";
|
||||
".mpeg" = mkDefault "01;35";
|
||||
".m2v" = mkDefault "01;35";
|
||||
".mkv" = mkDefault "01;35";
|
||||
".webm" = mkDefault "01;35";
|
||||
".ogm" = mkDefault "01;35";
|
||||
".mp4" = mkDefault "01;35";
|
||||
".m4v" = mkDefault "01;35";
|
||||
".mp4v" = mkDefault "01;35";
|
||||
".vob" = mkDefault "01;35";
|
||||
".qt" = mkDefault "01;35";
|
||||
".nuv" = mkDefault "01;35";
|
||||
".wmv" = mkDefault "01;35";
|
||||
".asf" = mkDefault "01;35";
|
||||
".rm" = mkDefault "01;35";
|
||||
".rmvb" = mkDefault "01;35";
|
||||
".flc" = mkDefault "01;35";
|
||||
".avi" = mkDefault "01;35";
|
||||
".fli" = mkDefault "01;35";
|
||||
".flv" = mkDefault "01;35";
|
||||
".gl" = mkDefault "01;35";
|
||||
".dl" = mkDefault "01;35";
|
||||
".xcf" = mkDefault "01;35";
|
||||
".xwd" = mkDefault "01;35";
|
||||
".yuv" = mkDefault "01;35";
|
||||
".cgm" = mkDefault "01;35";
|
||||
".emf" = mkDefault "01;35";
|
||||
".ogv" = mkDefault "01;35";
|
||||
".ogx" = mkDefault "01;35";
|
||||
".aac" = mkDefault "00;36";
|
||||
".au" = mkDefault "00;36";
|
||||
".flac" = mkDefault "00;36";
|
||||
".m4a" = mkDefault "00;36";
|
||||
".mid" = mkDefault "00;36";
|
||||
".midi" = mkDefault "00;36";
|
||||
".mka" = mkDefault "00;36";
|
||||
".mp3" = mkDefault "00;36";
|
||||
".mpc" = mkDefault "00;36";
|
||||
".ogg" = mkDefault "00;36";
|
||||
".ra" = mkDefault "00;36";
|
||||
".wav" = mkDefault "00;36";
|
||||
".oga" = mkDefault "00;36";
|
||||
".opus" = mkDefault "00;36";
|
||||
".spx" = mkDefault "00;36";
|
||||
".xspf" = mkDefault "00;36";
|
||||
};
|
||||
|
||||
home.file.".dir_colors".text = concatStringsSep "\n" ([ ]
|
||||
++ mapAttrsToList formatLine cfg.settings ++ [ "" ]
|
||||
++ optional (cfg.extraConfig != "") cfg.extraConfig);
|
||||
|
||||
programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
|
||||
eval $(${pkgs.coreutils}/bin/dircolors -b ~/.dir_colors)
|
||||
'';
|
||||
|
||||
programs.fish.shellInit = mkIf cfg.enableFishIntegration ''
|
||||
eval (${pkgs.coreutils}/bin/dircolors -c ~/.dir_colors)
|
||||
'';
|
||||
|
||||
# Set `LS_COLORS` before Oh My Zsh and `initExtra`.
|
||||
programs.zsh.initExtraBeforeCompInit = mkIf cfg.enableZshIntegration ''
|
||||
eval $(${pkgs.coreutils}/bin/dircolors -b ~/.dir_colors)
|
||||
'';
|
||||
};
|
||||
}
|
||||
100
modules/programs/direnv.nix
Normal file
100
modules/programs/direnv.nix
Normal file
@@ -0,0 +1,100 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.programs.direnv;
|
||||
|
||||
tomlFormat = pkgs.formats.toml { };
|
||||
|
||||
in {
|
||||
meta.maintainers = [ maintainers.rycee ];
|
||||
|
||||
options.programs.direnv = {
|
||||
enable = mkEnableOption "direnv, the environment switcher";
|
||||
|
||||
config = mkOption {
|
||||
type = tomlFormat.type;
|
||||
default = { };
|
||||
description = ''
|
||||
Configuration written to
|
||||
<filename>~/.config/direnv/config.toml</filename>.
|
||||
</para><para>
|
||||
See
|
||||
<citerefentry>
|
||||
<refentrytitle>direnv.toml</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry>.
|
||||
for the full list of options.
|
||||
'';
|
||||
};
|
||||
|
||||
stdlib = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Custom stdlib written to
|
||||
<filename>~/.config/direnv/direnvrc</filename>.
|
||||
'';
|
||||
};
|
||||
|
||||
enableBashIntegration = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Whether to enable Bash integration.
|
||||
'';
|
||||
};
|
||||
|
||||
enableZshIntegration = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Whether to enable Zsh integration.
|
||||
'';
|
||||
};
|
||||
|
||||
enableFishIntegration = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Whether to enable Fish integration.
|
||||
'';
|
||||
};
|
||||
|
||||
enableNixDirenvIntegration = mkEnableOption ''
|
||||
<link
|
||||
xlink:href="https://github.com/nix-community/nix-direnv">nix-direnv</link>,
|
||||
a fast, persistent use_nix implementation for direnv'';
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
home.packages = [ pkgs.direnv ];
|
||||
|
||||
xdg.configFile."direnv/config.toml" = mkIf (cfg.config != { }) {
|
||||
source = tomlFormat.generate "direnv-config" cfg.config;
|
||||
};
|
||||
|
||||
xdg.configFile."direnv/direnvrc" = let
|
||||
text = concatStringsSep "\n" (optional (cfg.stdlib != "") cfg.stdlib
|
||||
++ optional cfg.enableNixDirenvIntegration
|
||||
"source ${pkgs.nix-direnv}/share/nix-direnv/direnvrc");
|
||||
in mkIf (text != "") { inherit text; };
|
||||
|
||||
programs.bash.initExtra = mkIf cfg.enableBashIntegration (
|
||||
# Using mkAfter to make it more likely to appear after other
|
||||
# manipulations of the prompt.
|
||||
mkAfter ''
|
||||
eval "$(${pkgs.direnv}/bin/direnv hook bash)"
|
||||
'');
|
||||
|
||||
programs.zsh.initExtra = mkIf cfg.enableZshIntegration ''
|
||||
eval "$(${pkgs.direnv}/bin/direnv hook zsh)"
|
||||
'';
|
||||
|
||||
programs.fish.shellInit = mkIf cfg.enableFishIntegration ''
|
||||
${pkgs.direnv}/bin/direnv hook fish | source
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -6,22 +6,42 @@ let
|
||||
|
||||
cfg = config.programs.eclipse;
|
||||
|
||||
in
|
||||
in {
|
||||
meta.maintainers = [ maintainers.rycee ];
|
||||
|
||||
{
|
||||
options = {
|
||||
programs.eclipse = {
|
||||
enable = mkEnableOption "Eclipse";
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.eclipses.eclipse-platform;
|
||||
defaultText = literalExample "pkgs.eclipses.eclipse-platform";
|
||||
example = literalExample "pkgs.eclipses.eclipse-java";
|
||||
description = ''
|
||||
The Eclipse package to install.
|
||||
'';
|
||||
};
|
||||
|
||||
enableLombok = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
example = true;
|
||||
description = ''
|
||||
Whether to enable the Lombok Java Agent in Eclipse. This is
|
||||
necessary to use the Lombok class annotations.
|
||||
'';
|
||||
};
|
||||
|
||||
jvmArgs = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
description = "JVM arguments to use for the Eclipse process.";
|
||||
};
|
||||
|
||||
plugins = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = [];
|
||||
default = [ ];
|
||||
description = "Plugins that should be added to Eclipse.";
|
||||
};
|
||||
};
|
||||
@@ -30,8 +50,9 @@ in
|
||||
config = mkIf cfg.enable {
|
||||
home.packages = [
|
||||
(pkgs.eclipses.eclipseWithPlugins {
|
||||
eclipse = pkgs.eclipses.eclipse-platform;
|
||||
jvmArgs = cfg.jvmArgs;
|
||||
eclipse = cfg.package;
|
||||
jvmArgs = cfg.jvmArgs ++ optional cfg.enableLombok
|
||||
"-javaagent:${pkgs.lombok}/share/java/lombok.jar";
|
||||
plugins = cfg.plugins;
|
||||
})
|
||||
];
|
||||
|
||||
@@ -6,24 +6,68 @@ let
|
||||
|
||||
cfg = config.programs.emacs;
|
||||
|
||||
in
|
||||
# Copied from all-packages.nix, with modifications to support
|
||||
# overrides.
|
||||
emacsPackages = let epkgs = pkgs.emacsPackagesFor cfg.package;
|
||||
in epkgs.overrideScope' cfg.overrides;
|
||||
|
||||
emacsWithPackages = emacsPackages.emacsWithPackages;
|
||||
|
||||
in {
|
||||
meta.maintainers = [ maintainers.rycee ];
|
||||
|
||||
{
|
||||
options = {
|
||||
programs.emacs = {
|
||||
enable = mkEnableOption "Emacs";
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.emacs;
|
||||
defaultText = literalExample "pkgs.emacs";
|
||||
example = literalExample "pkgs.emacs25-nox";
|
||||
description = "The Emacs package to use.";
|
||||
};
|
||||
|
||||
extraPackages = mkOption {
|
||||
default = self: [];
|
||||
example = literalExample ''
|
||||
epkgs: [ epkgs.emms epkgs.magit ]
|
||||
default = self: [ ];
|
||||
type = hm.types.selectorFunction;
|
||||
defaultText = "epkgs: []";
|
||||
example = literalExample "epkgs: [ epkgs.emms epkgs.magit ]";
|
||||
description = ''
|
||||
Extra packages available to Emacs. To get a list of
|
||||
available packages run:
|
||||
<command>nix-env -f '<nixpkgs>' -qaP -A emacsPackages</command>.
|
||||
'';
|
||||
};
|
||||
|
||||
overrides = mkOption {
|
||||
default = self: super: { };
|
||||
type = hm.types.overlayFunction;
|
||||
defaultText = "self: super: {}";
|
||||
example = literalExample ''
|
||||
self: super: rec {
|
||||
haskell-mode = self.melpaPackages.haskell-mode;
|
||||
# ...
|
||||
};
|
||||
'';
|
||||
description = ''
|
||||
Allows overriding packages within the Emacs package set.
|
||||
'';
|
||||
};
|
||||
|
||||
finalPackage = mkOption {
|
||||
type = types.package;
|
||||
visible = false;
|
||||
readOnly = true;
|
||||
description = ''
|
||||
The Emacs package including any overrides and extra packages.
|
||||
'';
|
||||
description = "Extra packages available to Emacs.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
home.packages = [ (pkgs.emacsWithPackages cfg.extraPackages) ];
|
||||
home.packages = [ cfg.finalPackage ];
|
||||
programs.emacs.finalPackage = emacsWithPackages cfg.extraPackages;
|
||||
};
|
||||
}
|
||||
|
||||
81
modules/programs/feh.nix
Normal file
81
modules/programs/feh.nix
Normal file
@@ -0,0 +1,81 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.programs.feh;
|
||||
|
||||
bindingsOf = t: with types; attrsOf (nullOr (either t (listOf t)));
|
||||
|
||||
renderBindings = bindings:
|
||||
let
|
||||
enabled = filterAttrs (n: v: v != null) bindings;
|
||||
disabled = filterAttrs (n: v: v == null) bindings;
|
||||
render = mapAttrsToList renderBinding;
|
||||
in concatStringsSep "\n" (render disabled ++ render enabled);
|
||||
|
||||
renderBinding = func: key:
|
||||
if key == null then
|
||||
func
|
||||
else if isList key then
|
||||
concatStringsSep " " ([ func ] ++ map toString key)
|
||||
else
|
||||
"${func} ${toString key}";
|
||||
|
||||
in {
|
||||
options.programs.feh = {
|
||||
enable = mkEnableOption "feh - a fast and light image viewer";
|
||||
|
||||
buttons = mkOption {
|
||||
default = { };
|
||||
type = with types; bindingsOf (either str int);
|
||||
example = {
|
||||
zoom_in = 4;
|
||||
zoom_out = "C-4";
|
||||
prev_img = [ 3 "C-3" ];
|
||||
};
|
||||
description = ''
|
||||
Override feh's default mouse button mapping. If you want to disable an
|
||||
action, set its value to null. If you want to bind multiple buttons to
|
||||
an action, set its value to a list.
|
||||
See <link xlink:href="https://man.finalrewind.org/1/feh/#x425554544f4e53"/> for
|
||||
default bindings and available commands.
|
||||
'';
|
||||
};
|
||||
|
||||
keybindings = mkOption {
|
||||
default = { };
|
||||
type = bindingsOf types.str;
|
||||
example = {
|
||||
zoom_in = "plus";
|
||||
zoom_out = "minus";
|
||||
prev_img = [ "h" "Left" ];
|
||||
};
|
||||
description = ''
|
||||
Override feh's default keybindings. If you want to disable a keybinding
|
||||
set its value to null. If you want to bind multiple keys to an action,
|
||||
set its value to a list.
|
||||
See <link xlink:href="https://man.finalrewind.org/1/feh/#x4b455953"/> for
|
||||
default bindings and available commands.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [{
|
||||
assertion = ((filterAttrs (n: v: v == "") cfg.keybindings) == { });
|
||||
message =
|
||||
"To disable a keybinding, use `null` instead of an empty string.";
|
||||
}];
|
||||
|
||||
home.packages = [ pkgs.feh ];
|
||||
|
||||
xdg.configFile."feh/buttons" =
|
||||
mkIf (cfg.buttons != { }) { text = renderBindings cfg.buttons + "\n"; };
|
||||
|
||||
xdg.configFile."feh/keys" = mkIf (cfg.keybindings != { }) {
|
||||
text = renderBindings cfg.keybindings + "\n";
|
||||
};
|
||||
};
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user