Compare commits
552 Commits
a7833919a2
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| fc420fad72 | |||
| dfdc1063ba | |||
|
4ff120cc5d
|
|||
| 7c99b475e3 | |||
| 262b53c6c4 | |||
| 0ff6be3f81 | |||
|
86d20105e5
|
|||
|
6790bf1430
|
|||
|
e76668d3b1
|
|||
|
204b13781d
|
|||
| 0b9cf5a928 | |||
| 93831564a8 | |||
|
82d761b026
|
|||
|
742fd7941d
|
|||
|
cb74cd84e2
|
|||
|
89fdfc8e72
|
|||
|
0e9c3b4b27
|
|||
|
d5535a38ad
|
|||
|
01553b71fd
|
|||
|
ffff95f3b9
|
|||
|
674a50ea05
|
|||
| a2d52e1ec2 | |||
| 84c6e9b79d | |||
|
2d84bcdf7e
|
|||
|
935ba904bd
|
|||
| 8b0b5ee85a | |||
| a1297a417e | |||
|
5c54ede483
|
|||
|
f9086bd2ca
|
|||
| f9dfc4ca4c | |||
| a899448fda | |||
|
429c407548
|
|||
|
2fb8e3718b
|
|||
|
11097e32de
|
|||
| 9d1acf0fb3 | |||
| 7d95e7854c | |||
|
1972ea5bb9
|
|||
| 2b9b8e495c | |||
|
231162bd03
|
|||
|
94e4e0dfab
|
|||
| 7dca813556 | |||
|
0fe183c93e
|
|||
|
dd28fc784b
|
|||
|
7183ed712b
|
|||
| d91c0c8deb | |||
|
d2f3da4a23
|
|||
| 0d8a2110cf | |||
|
7ca9d19b93
|
|||
| 29daf01b95 | |||
| 4202be5d3a | |||
|
05db9b57d7
|
|||
| a690e814eb | |||
|
f2874bf890
|
|||
| d085d5c597 | |||
|
4a00bc5492
|
|||
| 5b1d90c59d | |||
| 11a9db5fad | |||
|
12ee2bac89
|
|||
|
6feaa0ea9e
|
|||
|
7bbd705d0f
|
|||
|
d9c8000f68
|
|||
|
8dba8a31fe
|
|||
| 6b484599ae | |||
| 6e6f276896 | |||
|
bbe8aaf88d
|
|||
|
f62404c692
|
|||
| 1192e62eaf | |||
| 2c624d1a28 | |||
| 69e59806df | |||
|
ba6146c343
|
|||
| 8951644c75 | |||
|
e180e8d452
|
|||
| 3155449ef6 | |||
|
528ce2a984
|
|||
|
afad1c9933
|
|||
|
ea66507c76
|
|||
|
3e00f4e321
|
|||
| 78f957b211 | |||
|
d6c37fe0ad
|
|||
|
e63fd8b525
|
|||
| c770afa6c4 | |||
| 49e487ac3b | |||
|
911e656e5e
|
|||
| 0f02def439 | |||
|
24cdfe4129
|
|||
| 1b69ff9a7f | |||
|
0ba43b6226
|
|||
|
b898cf1030
|
|||
| ce1722d97f | |||
|
f02714416c
|
|||
| cd08c0782e | |||
| 927d28c01a | |||
|
25fb02b7ac
|
|||
|
c126296935
|
|||
|
48e6a96c6d
|
|||
|
a5e6efc761
|
|||
| ca130ff612 | |||
| 51f2c020d1 | |||
|
5b43f3bbd3
|
|||
| 19e5225254 | |||
| c2506bdf9c | |||
|
c4980a15b1
|
|||
| ddaaf35c85 | |||
| 7a0e1f0930 | |||
|
ef384b9c7c
|
|||
|
fe59a7c22c
|
|||
|
1c671d71ac
|
|||
|
819a3b1541
|
|||
|
6ac647e0c1
|
|||
|
690bfd64d0
|
|||
|
d972de3df5
|
|||
|
413b8d8fa1
|
|||
| 27b6b22f6a | |||
| b6034114ad | |||
|
e651566e14
|
|||
| f6a3ba0453 | |||
|
cd08403416
|
|||
|
4ca008836c
|
|||
| 980834e961 | |||
| f2f4d4ef49 | |||
|
05ba0a4f10
|
|||
| 49c8191037 | |||
|
ab030d7ec0
|
|||
| 4f00b5a0f4 | |||
| 5c21788c8f | |||
|
625a58fa9f
|
|||
|
e20cff41d4
|
|||
| 5c24d2c72d | |||
| 92bcc49962 | |||
|
4197e7faec
|
|||
|
daf81bf0a4
|
|||
|
cbd5faa66c
|
|||
|
a65e05b661
|
|||
|
00f70e8558
|
|||
|
8d6ca1797a
|
|||
|
02c46ebea7
|
|||
|
5f4306b6ca
|
|||
|
4c51ef7a33
|
|||
|
67fb29687c
|
|||
| b4a58af23c | |||
|
073dbd9b14
|
|||
|
6cd0de7ccf
|
|||
| d23cbfc733 | |||
| 1bfcd519b8 | |||
|
e684eb6134
|
|||
|
ab2f03213b
|
|||
|
16e969ee15
|
|||
|
936f13f712
|
|||
|
3bb534f20b
|
|||
|
a4054de4f6
|
|||
|
c096433b5d
|
|||
|
36a03202c6
|
|||
|
e4ef26fe03
|
|||
|
424a3c76ab
|
|||
|
beb89e406a
|
|||
|
63e71ac9dd
|
|||
|
61a82540fb
|
|||
|
3ccc5d2210
|
|||
|
efa86e8eda
|
|||
| 83e8c52298 | |||
| f674ae303c | |||
|
29b69c7b03
|
|||
| 8c869cc1b9 | |||
| fcc2f6ccc2 | |||
|
38bce499bd
|
|||
|
f3533835be
|
|||
| 68eb3b0092 | |||
| 3362c33339 | |||
|
ec47b0671c
|
|||
|
8495cbaa24
|
|||
| fe3eb818ba | |||
| 5930514847 | |||
| 8068dcb312 | |||
|
7afb470a42
|
|||
|
4761c48d96
|
|||
| 0a83bd425c | |||
| 83d5bd2d40 | |||
|
de349a423e
|
|||
|
0250669306
|
|||
|
7caf75b940
|
|||
|
453b5f1d50
|
|||
|
5cf5ca07c5
|
|||
|
fbfc52e675
|
|||
|
b791010e48
|
|||
|
c6c13c2e99
|
|||
|
b82166872f
|
|||
|
ec99ceb018
|
|||
|
a422400d72
|
|||
|
2772b26704
|
|||
|
180ea9337f
|
|||
|
72920c04ce
|
|||
| 614c064524 | |||
| 5ee09bf13e | |||
|
390072e919
|
|||
| cd240f4460 | |||
| f6fd093850 | |||
|
67f22c8a60
|
|||
|
6f8fd855e4
|
|||
|
93829285d8
|
|||
|
533ab60321
|
|||
|
43b3cf51f6
|
|||
|
26b90ecc72
|
|||
|
b506f2aa39
|
|||
|
7a1a213add
|
|||
|
98a5cb4c7c
|
|||
|
93554695dc
|
|||
| 8852ed3108 | |||
| 47487ddcc0 | |||
|
2a5aef2a64
|
|||
| bdf4581b28 | |||
|
f92ac6ac37
|
|||
|
cb30f19c32
|
|||
|
4a5536aeb6
|
|||
| 5103ddc43d | |||
| 29637799f6 | |||
|
ec1f00320b
|
|||
|
878bc360d9
|
|||
|
6bd6436c81
|
|||
| a76e4de605 | |||
| cf8dc8d7e1 | |||
|
d3851fcddc
|
|||
|
261e663e97
|
|||
| 83abb5b6c6 | |||
| 1433844c2b | |||
|
034ebade0d
|
|||
| 8dfbc2a9be | |||
|
ed8de40d46
|
|||
| d87582253c | |||
|
7079319a09
|
|||
| 3fcc8a3ab5 | |||
| fdd0733b3f | |||
|
c3e39b7a96
|
|||
|
c7d1e642e5
|
|||
| 3bdc712fa9 | |||
| b81cbd3b02 | |||
|
7474760525
|
|||
|
70f1ec2eeb
|
|||
|
46dd6cd3a9
|
|||
|
58e21eba95
|
|||
|
5cbb01497c
|
|||
| 7d277e52bd | |||
| dda63a05ff | |||
| 399f481adb | |||
| 6a6eff2d00 | |||
|
a9190cf7ec
|
|||
| 0c7f7df4ec | |||
| 70b4492986 | |||
|
1aac43af62
|
|||
|
68a9cd17bf
|
|||
|
7564604c53
|
|||
| 548df81c08 | |||
| b4bac6a562 | |||
|
2ff553f7b6
|
|||
|
914613c751
|
|||
|
78df24cba1
|
|||
|
4f266f691b
|
|||
|
ca0a35e8c7
|
|||
|
c2ec031af2
|
|||
| 3990bd13b4 | |||
| 429ccc3876 | |||
|
a7e6ae4d21
|
|||
|
5b74fbe427
|
|||
|
b998cc652e
|
|||
|
2e1750b5a4
|
|||
|
764f2253f6
|
|||
|
2e6abec499
|
|||
| 5c3d169572 | |||
| 50e4d92249 | |||
|
a5966fd982
|
|||
|
976f46757c
|
|||
|
2a7cb0f5cb
|
|||
|
8f845f7cf2
|
|||
|
69384f6427
|
|||
|
9f9248deb1
|
|||
|
3a054021cf
|
|||
|
015daec928
|
|||
|
d68bedef95
|
|||
|
e96f874469
|
|||
|
178214c812
|
|||
|
45cba3a15b
|
|||
|
11dc584104
|
|||
|
0167370823
|
|||
|
8d0f425b10
|
|||
|
a483c30c05
|
|||
|
3befc07887
|
|||
|
2a9a7ed2ff
|
|||
|
d1949953df
|
|||
|
7463d894f2
|
|||
|
1e1c2003f3
|
|||
|
e6de825fb1
|
|||
|
b6ed77d8f9
|
|||
|
522fd03c12
|
|||
| d68f68bec7 | |||
| a92847e6ed | |||
|
682e93c794
|
|||
|
953aafd055
|
|||
| 39688b28f4 | |||
|
654503062b
|
|||
| 9d2a498089 | |||
| 64c559dbab | |||
|
93fc5e0517
|
|||
| 1253f67c9c | |||
| 045f141e30 | |||
|
f76a45e273
|
|||
| 95f2ad9112 | |||
|
4210f3b445
|
|||
| 8b9bd248fd | |||
| b323fedf49 | |||
|
4f8c45c4ef
|
|||
|
16394da0d9
|
|||
|
7527f01a2b
|
|||
|
0670fbbdad
|
|||
|
b5513ccbde
|
|||
|
4c77f3b0af
|
|||
|
eb828a09d5
|
|||
|
ab284641a5
|
|||
|
fefcb9034b
|
|||
| e90cdeb259 | |||
| 3eec6c3f89 | |||
|
36a303f7d4
|
|||
|
5c224694ec
|
|||
|
bc0b67a498
|
|||
|
a3b60718de
|
|||
| 7744f4f569 | |||
| 4eea14576c | |||
|
681a48f3c5
|
|||
| 965d72230c | |||
| 71aa38c7ca | |||
|
499bf672f8
|
|||
|
477a4ab265
|
|||
|
bd0eac8413
|
|||
|
fc63b4f1b0
|
|||
|
0cbb7c6892
|
|||
|
35e86dcd6e
|
|||
|
4bfea67cc5
|
|||
| 85a7889c5c | |||
| 97f783e9a8 | |||
|
764a9d35e5
|
|||
|
cfd4749e72
|
|||
|
bddb068ec0
|
|||
|
608b0227cb
|
|||
|
5a018fe975
|
|||
|
cc14f7fb3d
|
|||
|
bff084db07
|
|||
|
f75d64bf9c
|
|||
|
43fd36f5ea
|
|||
|
9a820fc3e6
|
|||
|
d20f7f8d7b
|
|||
|
a4f6ee26cb
|
|||
|
c9174f9d4a
|
|||
|
c372c96dd7
|
|||
|
aa8e4437ec
|
|||
|
87960cc8cc
|
|||
| a9d1d6ac4d | |||
| fc17c9fd61 | |||
|
780bda7ab7
|
|||
| e4bcbd3da2 | |||
| 4bef8f9c91 | |||
|
e776e7fba6
|
|||
|
a170d82086
|
|||
|
c04c1a4bc2
|
|||
|
4c989a45c1
|
|||
|
cccef17031
|
|||
| b0debaa421 | |||
| 6edeb5bdd1 | |||
|
b64e7d4f3c
|
|||
|
251f512806
|
|||
|
43135aef02
|
|||
|
c909a4f054
|
|||
|
5394a6d494
|
|||
|
c9ac952553
|
|||
|
85be47582b
|
|||
| 8de2cf229b | |||
| 0cced863f8 | |||
|
7fcf268fc7
|
|||
|
76349ad94b
|
|||
|
eb1b780a80
|
|||
|
2ce41d0c55
|
|||
|
e30ccbc633
|
|||
|
7e266cb61a
|
|||
|
be3dd7494e
|
|||
|
0382d6ab9c
|
|||
|
f17229d0b8
|
|||
|
621d67e89e
|
|||
| f9ba0e20ea | |||
| 6d15701ad4 | |||
|
e30fc7a15c
|
|||
|
7bd080769e
|
|||
|
dc97892a29
|
|||
|
ce84db593c
|
|||
|
cdf850f2e7
|
|||
|
c5d6e35afc
|
|||
| 17dcc99fc2 | |||
|
831c7beb4d
|
|||
| f4157fb4ba | |||
|
79f8445e25
|
|||
| e86b537f6d | |||
|
23e2f43447
|
|||
| 32630443a8 | |||
| 21126012dc | |||
|
13eb93ce12
|
|||
|
8911146d3f
|
|||
|
1637dc3122
|
|||
|
bceff8f4ec
|
|||
|
d21aa4ed4b
|
|||
|
43123ff390
|
|||
|
8e7e450a9d
|
|||
|
d53237f53c
|
|||
| 8ad10c41d7 | |||
|
2f199066f8
|
|||
|
f444bfa464
|
|||
|
345d0086a5
|
|||
|
8e32196a79
|
|||
| 38bdc3df65 | |||
|
21437d1881
|
|||
|
fe6670f188
|
|||
| 27fd6e4e05 | |||
|
9cb9fff5ce
|
|||
|
a9ce4b9ada
|
|||
| 5e1fa470cb | |||
| bf2ad2f1e7 | |||
|
de07040c16
|
|||
|
9795164eda
|
|||
|
c098498f0c
|
|||
|
8ea448adb8
|
|||
|
8541ef2658
|
|||
|
761ac9eb1b
|
|||
|
9779dcc8ec
|
|||
| ea1aa20ac7 | |||
|
b6aa81f3b1
|
|||
|
91ee993302
|
|||
| 97b65c56a8 | |||
| 9959bd4dc6 | |||
|
278ceb2c06
|
|||
|
945b8ddabf
|
|||
|
bc8339895a
|
|||
|
c9d360809d
|
|||
|
e2738f2ab4
|
|||
|
d4f99a79fe
|
|||
|
b03ec287b2
|
|||
| 0959d82018 | |||
| fe1ef6f2ee | |||
|
569d17a342
|
|||
| cf56f58dcd | |||
|
4117b0ddb6
|
|||
| b2dd199e2f | |||
|
7359c12e79
|
|||
|
c9a5577c11
|
|||
|
329dae0f08
|
|||
| dbddc4c1de | |||
| 103f99b9f7 | |||
|
ba92267a80
|
|||
|
cb4d74423a
|
|||
|
368b714a98
|
|||
|
02c27c6907
|
|||
| b37f5c1d74 | |||
|
014a8c3515
|
|||
|
00055a7c38
|
|||
| 0dfd75923d | |||
|
1341e2559e
|
|||
| 0396d685fd | |||
|
90a813c9d3
|
|||
|
8b9daf40c5
|
|||
|
2a08e1acef
|
|||
| fe1905ec85 | |||
|
13b9ba5828
|
|||
|
c2afa1201f
|
|||
|
4df10a7a2c
|
|||
|
e063763c0e
|
|||
|
c97c2290eb
|
|||
| 40021dcc21 | |||
|
7610a4121d
|
|||
|
fd1ddddbf0
|
|||
| 15596bae5f | |||
|
db33d9cff7
|
|||
| 3bc28fd9d5 | |||
|
f97272d0ec
|
|||
| 0298e5a483 | |||
|
378cb6b221
|
|||
| 9bff3f3c69 | |||
|
1ef4bb9f0a
|
|||
| a88800f94f | |||
|
e4743bc8e2
|
|||
| 06b9210cc5 | |||
|
2e7f2d07e4
|
|||
| 013cf95478 | |||
|
724c631cd0
|
|||
|
31a1c4089a
|
|||
|
d7afc7dd6b
|
|||
|
9f917be2b2
|
|||
| 08ae7cbd5e | |||
|
ed11877ff4
|
|||
|
508f0798fa
|
|||
|
abbed56813
|
|||
|
4a9ff30519
|
|||
|
af979db1b0
|
|||
| 55dc402b3b | |||
|
1d71323cc8
|
|||
|
e075c40c9d
|
|||
|
b643c9195b
|
|||
|
a95bc4a11c
|
|||
| 0e766b3326 | |||
|
a7510cc8ea
|
|||
|
a351e62a17
|
|||
|
7936a0966e
|
|||
|
fee2d99bea
|
|||
|
7d4e33bc7e
|
|||
|
782ef833c2
|
|||
|
8917442089
|
|||
|
8d9e7ae43f
|
|||
|
9e7539d863
|
|||
|
6fd1e3221e
|
|||
|
df7c921bc6
|
|||
|
abbbf20b40
|
|||
|
a70e88c344
|
|||
|
a7c6b9097d
|
|||
|
0e7e824085
|
|||
|
a3d99eec3f
|
|||
|
a86f797627
|
|||
|
1a6f1f3f2c
|
|||
|
b82766ad52
|
|||
|
9b342114aa
|
|||
|
f09006846b
|
|||
|
2df665a537
|
|||
|
46be262f92
|
|||
| a442315312 | |||
|
6530935652
|
|||
|
bdbdf2e8e0
|
|||
|
d7471e2eca
|
|||
|
7acd099b3e
|
|||
|
e502cff8cb
|
|||
| 50979acc1f | |||
|
4aea2f4e2c
|
|||
| be051daf1e | |||
|
05139354cf
|
|||
|
d2e7c799c4
|
|||
| 233d75434c | |||
|
520217d4a9
|
|||
|
4e255f4502
|
|||
|
6d91f49521
|
|||
|
2e3230974c
|
|||
|
f93f9844dc
|
|||
| 9467d2c206 | |||
|
b62c2476da
|
|||
| 4dff7632cd | |||
|
f70dccdc65
|
|||
| 9f524694cb | |||
|
37f35ce0a0
|
|||
| b08a3d364e | |||
|
95f26eadc1
|
|||
| 337fb10cd4 | |||
|
d8bd2b32ab
|
@@ -0,0 +1,82 @@
|
|||||||
|
name: Generate documentation
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- "docs/manual/**"
|
||||||
|
- "docs/build-manual.py"
|
||||||
|
- "docs/manualtools.py"
|
||||||
|
- "docs/verify-manual.py"
|
||||||
|
- "docs/site/**"
|
||||||
|
- "functions/**"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-docs:
|
||||||
|
runs-on: racknerd-mini
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITEA_TOKEN }}
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get install -y pandoc python3-yaml
|
||||||
|
|
||||||
|
- name: Generate concatenated markdown
|
||||||
|
run: python3 docs/build-manual.py --concat -o docs/fish-config.md
|
||||||
|
|
||||||
|
# Regeneration MUST run before verification: verify-manual.py's
|
||||||
|
# test_concat_roundtrips_original compares a freshly-built concat
|
||||||
|
# against docs/fish-config.md on disk. Before this step ran, that
|
||||||
|
# file was still the stale pre-push copy, so any ordinary edit under
|
||||||
|
# docs/manual/** failed the round-trip check before anything was
|
||||||
|
# regenerated. Do not reorder this back — verification still gates
|
||||||
|
# pandoc and the auto-commit below, it just no longer requires a
|
||||||
|
# contributor to hand-sync the generated file before pushing.
|
||||||
|
- name: Verify manual integrity
|
||||||
|
run: python3 docs/verify-manual.py
|
||||||
|
|
||||||
|
- name: Compile man page
|
||||||
|
run: |
|
||||||
|
pandoc --standalone \
|
||||||
|
--from markdown \
|
||||||
|
--to man \
|
||||||
|
docs/fish-config.md \
|
||||||
|
-o docs/fish-config.1
|
||||||
|
|
||||||
|
- name: Set up Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "24"
|
||||||
|
|
||||||
|
- name: Build documentation site
|
||||||
|
run: |
|
||||||
|
python3 docs/build-manual.py --site
|
||||||
|
cd docs/site
|
||||||
|
npm ci
|
||||||
|
npx astro build
|
||||||
|
|
||||||
|
- name: Deploy to Cloudflare Pages
|
||||||
|
env:
|
||||||
|
CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
|
||||||
|
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
|
||||||
|
run: |
|
||||||
|
cd docs/site
|
||||||
|
npx --yes wrangler pages deploy dist/ \
|
||||||
|
--project-name=fish-config-docs \
|
||||||
|
--branch=main \
|
||||||
|
--commit-dirty=true
|
||||||
|
|
||||||
|
- name: Commit generated docs
|
||||||
|
run: |
|
||||||
|
git config user.name "Gitea Actions"
|
||||||
|
git config user.email "actions@gitea"
|
||||||
|
git add docs/fish-config.md docs/fish-config.1
|
||||||
|
git diff --cached --quiet && echo "No changes to commit" && exit 0
|
||||||
|
git commit -m "chore(docs): regenerate manual and man page"
|
||||||
|
git push
|
||||||
+294
-22
@@ -1,37 +1,309 @@
|
|||||||
# GitIgnore for Fish-config
|
# GitIgnore for Fish-config
|
||||||
|
|
||||||
|
# id: gitig-boilerplate-7f0528027e23f210196ae4583c408e5b
|
||||||
|
# ╭──────────────────────────────────────────────────────────╮
|
||||||
|
# │ GitIgnore Boilerplate Template │
|
||||||
|
# ╰──────────────────────────────────────────────────────────╯
|
||||||
|
#
|
||||||
|
# ──────────────────── OS-Generated Files ────────────────────
|
||||||
|
# automatic backup files created by some editors (e.g., Vim, Emacs)
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files created if a process still has a handle to a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# MacOS junk
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# files created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
# ─────────────────── Debug/Temporary/Testing ────────────────
|
||||||
|
# Matches OLD / .OLD
|
||||||
|
[Oo][Ll][Dd]/
|
||||||
|
.[Oo][Ll][Dd]/
|
||||||
|
|
||||||
|
# Matches DISABLE / .DISABLE
|
||||||
|
[Dd][Ii][Ss][Aa][Bb][Ll][Ee]/
|
||||||
|
.[Dd][Ii][Ss][Aa][Bb][Ll][Ee]/
|
||||||
|
|
||||||
|
# Matches DISABLED / .DISABLED
|
||||||
|
[Dd][Ii][Ss][Aa][Bb][Ll][Ee][Dd]/
|
||||||
|
.[Dd][Ii][Ss][Aa][Bb][Ll][Ee][Dd]/
|
||||||
|
|
||||||
|
# Matches DEBUG / .DEBUG
|
||||||
|
[Dd][Ee][Bb][Uu][Gg]/
|
||||||
|
.[Dd][Ee][Bb][Uu][Gg]/
|
||||||
|
|
||||||
|
# Matches TMP / .TMP
|
||||||
|
[Tt][Mm][Pp]/
|
||||||
|
.[Tt][Mm][Pp]/
|
||||||
|
|
||||||
|
# Matches TEMP / .TEMP
|
||||||
|
[Tt][Ee][Mm][Pp]/
|
||||||
|
.[Tt][Ee][Mm][Pp]/
|
||||||
|
|
||||||
|
# Matches TEMPORARY / .TEMPORARY
|
||||||
|
[Tt][Ee][Mm][Pp][Oo][Rr][Aa][Rr][Yy]/
|
||||||
|
.[Tt][Ee][Mm][Pp][Oo][Rr][Aa][Rr][Yy]/
|
||||||
|
|
||||||
|
# Matches TESTING / .TESTING
|
||||||
|
[Tt][Ee][Ss][Tt][Ii][Nn][Gg]/
|
||||||
|
.[Tt][Ee][Ss][Tt][Ii][Nn][Gg]/
|
||||||
|
|
||||||
|
# ──────────────────── Planning Artifacts ───────────────────
|
||||||
|
# Catalog files generated by pre-implementation analysis passes
|
||||||
|
opinionated_catalog.md
|
||||||
|
.superpowers
|
||||||
|
docs/superpowers
|
||||||
|
docs/specs
|
||||||
|
docs/plans
|
||||||
|
|
||||||
|
# ──────────────────── Runtime State Files ───────────────────
|
||||||
|
# Sentinel file written/removed at runtime to coordinate logging state
|
||||||
|
# across the fish config and the Kitty Python watcher. Never committed.
|
||||||
|
.logging_disabled
|
||||||
|
|
||||||
|
# ──────────────── Fisher-Managed Plugin Files ───────────────
|
||||||
|
# Fisher writes these into the repo directory on install/update.
|
||||||
|
# They are owned by Fisher — do not commit them.
|
||||||
|
functions/fisher.fish
|
||||||
|
completions/fisher.fish
|
||||||
|
conf.d/sponge.fish
|
||||||
|
functions/_sponge*.fish
|
||||||
|
functions/sponge_*.fish
|
||||||
|
!functions/sponge_filter_secrets.fish
|
||||||
|
|
||||||
|
# ─────────────────── AI Sessions and Rules ──────────────────
|
||||||
|
# Matches CLAUDE.md, .claud*, etc.
|
||||||
|
[Cc][Ll][Aa][Uu][Dd][Ee].[Mm][Dd]
|
||||||
|
.[Cc][Ll][Aa][Uu][Dd]*
|
||||||
|
|
||||||
|
# Matches GEMINI.md, .gemin*, etc.
|
||||||
|
[Gg][Ee][Mm][Ii][Nn][Ii].[Mm][Dd]
|
||||||
|
.[Gg][Ee][Mm][Ii][Nn]*
|
||||||
|
|
||||||
|
# Matches ANTIGRAVITY.md, .antigrav*, etc.
|
||||||
|
[Aa][nN][Tt][Ii][Gg][Rr][Aa][Vv][Ii][Tt][Yy].[Mm][Dd]
|
||||||
|
.[Aa][Nn][Tt][Ii][Gg][Rr][Aa][Vv]*
|
||||||
|
|
||||||
|
# Matches AGENTS.md, .remember, etc.
|
||||||
|
[Aa][Gg][Ee][Nn][Tt][Ss].[Mm][Dd]
|
||||||
|
.[Rr][Ee][Mm][Ee][Mm][Bb][Ee][Rr]
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
# id: gi-patterns-a62e4f6489ac26edaabdfc550334800a
|
||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/fish
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=fish
|
||||||
|
|
||||||
### Fish ###
|
### Fish ###
|
||||||
fishd.*
|
fishd.*
|
||||||
fish_history
|
fish_history
|
||||||
fish_variables
|
fish_variables
|
||||||
config.local.fish
|
config.local.fish
|
||||||
|
|
||||||
### Linux ###
|
# End of https://www.toptal.com/developers/gitignore/api/fish
|
||||||
*~
|
|
||||||
|
|
||||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
# id: gi-patterns-e390e9c720b3dda36906a2b4cb76ffdd
|
||||||
.fuse_hidden*
|
# Created by https://www.toptal.com/developers/gitignore/api/python
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=python
|
||||||
|
|
||||||
# KDE directory preferences
|
### Python ###
|
||||||
.directory
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
# Linux trash folder which might appear on any partition or disk
|
# C extensions
|
||||||
.Trash-*
|
*.so
|
||||||
|
|
||||||
# .nfs files are created when an open file is removed but is still being accessed
|
# Distribution / packaging
|
||||||
.nfs*
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
# Debug Files/Folders
|
# PyInstaller
|
||||||
OLD/
|
# Usually these files are written by a python script from a template
|
||||||
*.OLD
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
*.DISABLE
|
*.manifest
|
||||||
*.DISABLED
|
*.spec
|
||||||
*_old
|
|
||||||
|
|
||||||
# AI Session IDs
|
# Installer logs
|
||||||
.claude_session
|
pip-log.txt
|
||||||
.gemini_session
|
pip-delete-this-directory.txt
|
||||||
.remember/
|
|
||||||
|
|
||||||
# Auto-managed by fish; contains machine-local state and universal vars
|
# Unit test / coverage reports
|
||||||
fish_variables
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
#pdm.lock
|
||||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
|
# in version control.
|
||||||
|
# https://pdm.fming.dev/#use-with-ide
|
||||||
|
.pdm.toml
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#.idea/
|
||||||
|
|
||||||
|
### Python Patch ###
|
||||||
|
# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
|
||||||
|
poetry.toml
|
||||||
|
|
||||||
|
# ruff
|
||||||
|
.ruff_cache/
|
||||||
|
|
||||||
|
# LSP config files
|
||||||
|
pyrightconfig.json
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/python
|
||||||
|
|
||||||
|
# ──────────────── Added by agents-init ──────────────────
|
||||||
|
# agents-init --agents
|
||||||
|
AGENTS/
|
||||||
|
# ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
# ──────────────── Added by agents-init ──────────────────
|
||||||
|
# agents-init --plugins
|
||||||
|
docs/devlogs
|
||||||
|
# ────────────────────────────────────────────────────────
|
||||||
|
/.cache_ggshield
|
||||||
|
user-dots
|
||||||
|
|
||||||
|
# ──────────────────── Generated Docs Site ───────────────────
|
||||||
|
docs/site/node_modules/
|
||||||
|
docs/site/dist/
|
||||||
|
docs/site/.astro/
|
||||||
|
docs/site/src/content/docs/
|
||||||
|
docs/site/src/sidebar.json
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
# Fish Shell Configuration
|
# Fish Shell Configuration
|
||||||
|
|
||||||
A feature-rich Fish shell configuration for CachyOS (Arch Linux), built around a Catppuccin Mocha aesthetic with a curated set of modern CLI tool integrations, smart shell functions, and a heavily customized abbreviation system for keyboard-driven workflows.
|
A feature-rich Fish shell configuration for CachyOS (Arch Linux),
|
||||||
|
built around a Catppuccin Mocha aesthetic with a curated set of modern
|
||||||
|
CLI tool integrations, smart shell functions, and a heavily customized
|
||||||
|
abbreviation system for keyboard-driven workflows.
|
||||||
|
|
||||||
|
📖 **[Documentation site](https://fish.rootiest.fyi/)**
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
- [Overview](#overview)
|
- [Overview](#overview)
|
||||||
- [Structure](#structure)
|
- [Session Logging](#session-logging)
|
||||||
- [Plugins](#plugins)
|
- [Documentation](#documentation)
|
||||||
- [Theme & Prompt](#theme--prompt)
|
|
||||||
- [Integrations](#integrations)
|
|
||||||
- [Key Bindings](#key-bindings)
|
|
||||||
- [Functions](#functions)
|
|
||||||
- [Abbreviations](#abbreviations)
|
|
||||||
- [Dependencies](#dependencies)
|
|
||||||
- [Installation](#installation)
|
- [Installation](#installation)
|
||||||
- [Personalization](#personalization)
|
- [Personalization](#personalization)
|
||||||
- [Full Requirements](#full-requirements)
|
- [Minimal Mode](#minimal-mode)
|
||||||
|
- [Attribution](#attribution)
|
||||||
- [License](#license)
|
- [License](#license)
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -24,462 +24,141 @@ A feature-rich Fish shell configuration for CachyOS (Arch Linux), built around a
|
|||||||
|
|
||||||
This config layers on top of the CachyOS base Fish configuration and adds:
|
This config layers on top of the CachyOS base Fish configuration and adds:
|
||||||
|
|
||||||
- **Catppuccin Mocha** theming throughout (prompt, FZF, Zellij)
|
- **Catppuccin Mocha** theming throughout (prompt, FZF, syntax highlighting)
|
||||||
- **Starship** prompt with VI key bindings
|
- **Starship** prompt with VI key bindings; Catppuccin Mocha nim-style fallback prompt when Starship is absent or C3 overrides are disabled
|
||||||
- **Fisher** plugin management with FZF key bindings and Catppuccin syntax colors
|
- **Fisher** plugin manager bootstrapped automatically; manages `sponge` (failed-command history filter); FZF bindings, Catppuccin theme, done, autopair, and puffer-fish are bundled directly with the config as customized versions
|
||||||
- **Smart CLI wrappers** that prefer modern tools (`eza`, `bat`, `btop`, `dust`, `prettyping`) with graceful fallbacks
|
- **Smart CLI wrappers** that prefer modern tools (`eza`, `bat`, `btop`, `dust`, `prettyping`) with graceful fallbacks
|
||||||
- **Auto Python venv** activation on directory change (direnv-aware)
|
- **Auto Python venv** activation on directory change (direnv-aware)
|
||||||
- **Kitty terminal** deep integration for splits, tabs, and SSH
|
- **Kitty terminal** deep integration for splits, tabs, and SSH
|
||||||
- **AI workflow** helpers for Claude and Gemini session management
|
- **Named background jobs** — `jobrunner` (short: `jr`) starts, lists, inspects, re-attaches to, and kills detached tasks via `tmux` or GNU `screen`, so long-running work survives closing the shell
|
||||||
|
- **Optional session logging** — terminal scrollback, multiplexer panes (tmux/zellij), and AUR-helper output can be captured to `~/.terminal_history`; **off by default**, opt in when you want it (see the caution below and [Session Logging](#session-logging))
|
||||||
|
- **AI workflow** helpers for Claude and Antigravity session management
|
||||||
- **WakaTime** shell activity tracking
|
- **WakaTime** shell activity tracking
|
||||||
|
- **Opt-out toggles** for every opinionated component — see [Minimal Mode](#minimal-mode)
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> **This configuration *can* log your terminal sessions to disk.** Logging is
|
||||||
|
> **off by default** — but once enabled it silently captures terminal output to
|
||||||
|
> `~/.terminal_history`: Kitty scrollback when a window closes, live tmux pane
|
||||||
|
> streams, zellij pane snapshots on exit, and full `paru`/`yay` output. These
|
||||||
|
> logs can contain command output, file contents, and anything else printed to
|
||||||
|
> your terminal. Nothing is sent off your machine, but the files persist
|
||||||
|
> locally until pruned.
|
||||||
|
>
|
||||||
|
> To turn logging on, set the C5 category variable:
|
||||||
|
>
|
||||||
|
> ```fish
|
||||||
|
> set -U __fish_config_op_logging on
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> Or run **`config-settings`** for an interactive menu to flip logging (and any
|
||||||
|
> other opinionated category) on or off — no variable names to remember.
|
||||||
|
>
|
||||||
|
> This takes effect immediately in every open shell. See [Session Logging](#session-logging)
|
||||||
|
> for exactly what is captured and where, and [Minimal Mode](#minimal-mode) for the
|
||||||
|
> full set of opt-out toggles.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Structure
|
## Session Logging
|
||||||
|
|
||||||
```
|
This config can capture terminal output to `~/.terminal_history` (override with
|
||||||
~/.config/fish/
|
`$SCROLLBACK_HISTORY_DIR`) so you can search back through past sessions. It is
|
||||||
├── config.fish # Main entry point
|
**off by default** — opt in with `set -U __fish_config_op_logging on`. Once
|
||||||
├── fish_plugins # Fisher plugin list
|
enabled, five sources feed it:
|
||||||
├── fish_variables # Universal variables
|
|
||||||
├── conf.d/ # Auto-sourced configuration fragments
|
|
||||||
│ ├── abbr.fish # All abbreviations
|
|
||||||
│ ├── cheat.fish # cheat.sh completions
|
|
||||||
│ ├── key_bindings.fish # Custom key bindings
|
|
||||||
│ ├── fzf.fish # FZF key binding initialization
|
|
||||||
│ ├── tailscale.fish # Tailscale CLI completions
|
|
||||||
│ ├── theme.fish # Theme syntax highlighting colors
|
|
||||||
│ ├── wakatime.fish # WakaTime shell hook
|
|
||||||
│ └── zoxide.fish # Zoxide z/zi aliases
|
|
||||||
├── functions/ # Custom functions (one per file)
|
|
||||||
├── completions/ # Custom tab completions
|
|
||||||
├── integrations/ # Integration scripts
|
|
||||||
│ └── fzf.fish # FZF theme and binding config
|
|
||||||
└── themes/ # Catppuccin theme files
|
|
||||||
├── Catppuccin Mocha.theme
|
|
||||||
├── Catppuccin Macchiato.theme
|
|
||||||
├── Catppuccin Frappe.theme
|
|
||||||
└── Catppuccin Latte.theme
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
| Source | When it captures | Log file |
|
||||||
|
|
||||||
## Plugins
|
|
||||||
|
|
||||||
Managed via [Fisher](https://github.com/jorgebucaran/fisher):
|
|
||||||
|
|
||||||
| Plugin | Purpose |
|
|
||||||
|---|---|
|
|
||||||
| `jorgebucaran/fisher` | Plugin manager |
|
|
||||||
| `patrickf1/fzf.fish` | FZF key bindings for history, files, processes, git |
|
|
||||||
| `catppuccin/fish` | Catppuccin Mocha syntax highlighting |
|
|
||||||
| `jorgebucaran/autopair.fish` | Auto-close brackets, quotes, and other pairs |
|
|
||||||
| `jorgebucaran/replay.fish` | Run bash commands in fish without losing state |
|
|
||||||
| `nickeb96/puffer-fish` | Expand `...` to `../..`, `!!` to last command, etc. |
|
|
||||||
| `mattmc3/magic-enter.fish` | Smart Enter: runs `ls` / `git status` on blank line |
|
|
||||||
| `jorgebucaran/spark.fish` | Sparkline bar charts in the terminal |
|
|
||||||
|
|
||||||
Fisher and all listed plugins are installed automatically by the bootstrap script in `config.fish` upon launching the shell for the first time.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Theme & Prompt
|
|
||||||
|
|
||||||
### Starship
|
|
||||||
|
|
||||||
The primary prompt is [Starship](https://starship.rs/), initialized in `config.fish`. Configure it via `~/.config/starship.toml`.
|
|
||||||
|
|
||||||
### FZF
|
|
||||||
|
|
||||||
FZF is themed to Catppuccin Mocha with the following colors set via `FZF_DEFAULT_OPTS`:
|
|
||||||
|
|
||||||
- Background: `#1E1E2E` / `#313244`
|
|
||||||
- Foreground: `#CDD6F4`
|
|
||||||
- Highlights: `#F38BA8` (red), `#CBA6F7` (mauve), `#B4BEFE` (lavender)
|
|
||||||
|
|
||||||
See [FZF Bindings](#fzf-bindings) under Key Bindings for the default FZF shortcuts.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Integrations
|
|
||||||
|
|
||||||
> **Note:** All integrations listed below are designed to gracefully fallback to basic commands or safely ignore their configuration if their required external dependencies are not installed on the system.
|
|
||||||
|
|
||||||
### Zoxide
|
|
||||||
|
|
||||||
Smart `cd` replacement. `cd` (or `z`) `<keyword>` jumps to the best frecency match; `cdi` (or `zi`) opens an interactive selector.
|
|
||||||
|
|
||||||
### DirEnv
|
|
||||||
|
|
||||||
Automatically loads `.envrc` files on directory change. Takes priority over the built-in auto-venv logic.
|
|
||||||
|
|
||||||
### Auto Python Venv
|
|
||||||
|
|
||||||
When entering a directory containing a `.venv/`, the virtualenv is automatically activated. It is deactivated when you leave the project tree. DirEnv-managed directories are skipped to avoid conflicts.
|
|
||||||
|
|
||||||
### WakaTime
|
|
||||||
|
|
||||||
Every shell command is reported to WakaTime for time-tracking. Disable by setting `FISH_WAKATIME_DISABLED=1`.
|
|
||||||
|
|
||||||
### Tailscale
|
|
||||||
|
|
||||||
Full tab completion for the `tailscale` CLI is provided via `conf.d/tailscale.fish`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Key Bindings
|
|
||||||
|
|
||||||
### FZF Bindings
|
|
||||||
|
|
||||||
These are the default FZF bindings (from `fzf.fish`):
|
|
||||||
|
|
||||||
| Binding | Action |
|
|
||||||
|---|---|
|
|
||||||
| `Ctrl+R` | Search command history |
|
|
||||||
| `Ctrl+Alt+F` | Search git-tracked files |
|
|
||||||
| `Ctrl+Alt+L` | Search git log |
|
|
||||||
| `Ctrl+Alt+S` | Search git status |
|
|
||||||
| `Ctrl+V` | Search shell variables |
|
|
||||||
| `Ctrl+Alt+P` | Search running processes |
|
|
||||||
|
|
||||||
### User Bindings
|
|
||||||
|
|
||||||
Beyond standard shell and FZF bindings, these custom interactive shortcuts are available:
|
|
||||||
|
|
||||||
| Binding | Action | Description |
|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `Ctrl+G` | Previous Path Head | Behaves like `!$:h` in Bash. Inserts the directory part of the previous command's last argument. |
|
| Kitty scrollback | When a Kitty window/tab closes | `scrollback_<timestamp>.log` |
|
||||||
| `Ctrl+F` | Interactive History Substitution | Behaves like `!!:s/old/new/` in Bash. Performs substitution on the previous command using `old/new` syntax. When no text is entered, prepends `sudo` to the previous command. The `old/new/n` syntax will perform substitution on the command `n` lines previous in the history. |
|
| tmux pane | Continuously while the pane is open (`pipe-pane`) | `tmux_<session>-w<win>-p<pane>_<timestamp>.log` |
|
||||||
| `Ctrl+Alt+U` | Replace Command Token | Strips the first token (the command) from the current line. **If the line is empty**, it pulls the previous command and strips its first token, placing the cursor at the start for a quick replacement (e.g., changing `mkdir` to `cd` while keeping the paths). |
|
| zellij pane | Snapshot taken on **clean** shell exit (`dump-screen`) | `zellij_<session>-p<pane>_<timestamp>.log` |
|
||||||
|
| `paru` wrapper | Every `paru` invocation | `paru_<timestamp>.log` |
|
||||||
|
| `yay` wrapper | Every `yay` invocation | `yay_<timestamp>.log` |
|
||||||
|
|
||||||
---
|
Old logs are pruned automatically to stay within `$SCROLLBACK_HISTORY_MAX_FILES`
|
||||||
|
(default 100) per source, and empty/trivial captures are discarded.
|
||||||
|
|
||||||
## Functions
|
> **zellij caveat:** zellij has no continuous pipe like tmux, so its pane is
|
||||||
|
> snapshotted only on a clean shell exit (`exit`/Ctrl-D). Closing a pane or
|
||||||
|
> quitting zellij directly tears down the pane/server before it can be dumped,
|
||||||
|
> so those sessions are not logged. End with `exit` to guarantee a log.
|
||||||
|
|
||||||
### Modern CLI Replacements
|
**These logs can contain secrets** — anything printed to your terminal (command
|
||||||
|
output, file dumps, tokens echoed to stdout) ends up in them. They never leave
|
||||||
|
your machine, but treat `~/.terminal_history` as sensitive.
|
||||||
|
|
||||||
These functions wrap modern alternatives with graceful fallbacks to standard tools.
|
All of it is controlled by a single universal variable:
|
||||||
|
|
||||||
| Function | Replaces | Tool |
|
|
||||||
|---|---|---|
|
|
||||||
| `ls` | `ls` | `eza` (falls back to `lsd`, then system `ls`) |
|
|
||||||
| `cat` | `cat` | `bat` (plain, no pager) |
|
|
||||||
| `less` | `less` | `most` |
|
|
||||||
| `ping` | `ping` | `prettyping --nolegend` |
|
|
||||||
| `top` | `top` | `btop` |
|
|
||||||
| `rg` | `rg` | ripgrep with `--hyperlink-format=kitty` |
|
|
||||||
| `ssh` | `ssh` | `kitten ssh` when inside Kitty |
|
|
||||||
| `du` | `du` | `duf` (disks) / `dust` (directories) — auto-detected by argument |
|
|
||||||
| `mkdir` | `mkdir` | Always passes `-p` in interactive mode |
|
|
||||||
|
|
||||||
#### `du` — Smart Disk Usage
|
|
||||||
|
|
||||||
```fish
|
```fish
|
||||||
du # → duf (disk overview)
|
set -U __fish_config_op_logging on # enable; takes effect in every open shell
|
||||||
du /some/dir # → dust (directory breakdown)
|
set -U __fish_config_op_logging off # disable again
|
||||||
du --disk # → duf (force disk view)
|
set -Ue __fish_config_op_logging # erase — back to the default (off)
|
||||||
du --dir # → dust (force directory view)
|
|
||||||
du --dua # → dua (interactive mode)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `rm` — Trash-Aware Remove
|
Unlike the other categories, C5 is opt-in: an unset variable means off, and
|
||||||
|
`__fish_config_opinionated` cannot turn it on for you.
|
||||||
|
|
||||||
```fish
|
Prefer an interactive interface? Run **`config-settings`** for a full-screen
|
||||||
rm # List current trash contents
|
picker that flips logging — and every other opinionated category — on or off
|
||||||
rm file.txt # Move to trash (recoverable)
|
per session or universally, without memorizing variable names.
|
||||||
rm -r dir/ # Move directory to trash
|
|
||||||
rm -e # Empty all trash
|
|
||||||
rm -e --within 2weeks # Empty trash older than 2 weeks
|
|
||||||
rm -S file.txt # Permanent secure delete + fstrim
|
|
||||||
rm -f file.txt # Falls through to standard rm -f
|
|
||||||
```
|
|
||||||
|
|
||||||
### Directory & File Listing
|
Disabling (or leaving it unset) also removes the generated `paru`/`yay` log
|
||||||
|
wrappers and tells the Kitty watcher to skip capture via a sentinel file — no
|
||||||
|
shell or terminal restart required. Logging is category **C5** in
|
||||||
|
[Minimal Mode](#minimal-mode); `set -U __fish_config_opinionated 0` keeps it
|
||||||
|
off along with everything else.
|
||||||
|
|
||||||
| Function | Description |
|
The Kitty scrollback capture is provided by a watcher script that fish-config can
|
||||||
|
install and manage for you. Inside Kitty, if it isn't set up yet, you'll see a
|
||||||
|
one-time-per-session reminder. Manage it with:
|
||||||
|
|
||||||
|
| Command | Action |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `ls` | `eza` — long listing, all files, icons, color, hyperlinks |
|
| `kitty-logging install` | Symlink the watcher into your Kitty config and wire it into `kitty.conf` |
|
||||||
| `lss` | `eza` — size-sorted long listing with gradient color scale |
|
| `kitty-logging uninstall` | Remove the managed block and the watcher symlink |
|
||||||
| `lsr` | `eza` — reversed time-sorted oneline listing |
|
| `kitty-logging status` | Show whether it's wired, the watcher version, and C5 state |
|
||||||
| `ltr` | `eza` — long listing, reversed modification time, age color scale |
|
| `kitty-logging dismiss` | Stop the per-session reminder without installing |
|
||||||
| `lD` | `eza` — directories only |
|
|
||||||
| `lx` | `eza` — long listing sorted by extension |
|
|
||||||
| `lt` | `eza` — tree listing, depth 2 |
|
|
||||||
| `lstree` | `eza` — full recursive tree |
|
|
||||||
|
|
||||||
### Git
|
`install` adds a clearly-marked managed block to `kitty.conf` and comments out
|
||||||
|
any conflicting `watcher` line. It affects **new** Kitty windows (existing
|
||||||
| Function | Description |
|
windows keep their current watcher until restarted). With C5 logging off the
|
||||||
|---|---|
|
watcher is inert without needing to be uninstalled, and the reminder stays
|
||||||
| `branch` | Switch to or create a git branch |
|
silent until you enable logging.
|
||||||
| `gitup` | Fetch updates and show git status |
|
|
||||||
| `git-clean` | Fetch, prune, update current branch, delete orphaned local branches |
|
|
||||||
| `git-clean --force` | Same but force-deletes unmerged orphaned branches |
|
|
||||||
| `clone` | `clone-in-kitty` wrapper |
|
|
||||||
| `gitui` | Fast terminal Git UI |
|
|
||||||
|
|
||||||
### Package Management (Arch / paru)
|
|
||||||
|
|
||||||
| Function | Description |
|
|
||||||
|---|---|
|
|
||||||
| `pkg <name>` | Install package: `paru -S <name>` |
|
|
||||||
| `search <query>` | Search/install interactively: `paru <query>` |
|
|
||||||
| `upgrade` | Full system upgrade: `paru -Syu --noconfirm` |
|
|
||||||
| `cleanup` | Log and remove orphaned packages |
|
|
||||||
|
|
||||||
### Docker
|
|
||||||
|
|
||||||
| Function | Description |
|
|
||||||
|---|---|
|
|
||||||
| `ld` / `lzd` | Launch LazyDocker using the currently active Docker context |
|
|
||||||
| `dockup [dir]` | Pull latest images and restart docker compose services |
|
|
||||||
| `docker ps` | Intercepted to use `dops` for a prettier process listing |
|
|
||||||
|
|
||||||
### Network
|
|
||||||
|
|
||||||
| Function | Description |
|
|
||||||
|---|---|
|
|
||||||
| `gip` | Show both public IPv4 and IPv6 addresses |
|
|
||||||
| `gip4` | Show public IPv4 address only |
|
|
||||||
| `gip6` | Show public IPv6 address (or error if unavailable) |
|
|
||||||
| `ports` | List all active TCP listeners via `lsof` |
|
|
||||||
|
|
||||||
### Clipboard
|
|
||||||
|
|
||||||
| Function | Description |
|
|
||||||
|---|---|
|
|
||||||
| `y <text>` | Copy text to clipboard (Wayland `wl-copy` or X11 `xclip`) |
|
|
||||||
| `cb <text>` | Copy to clipboard (alias for `y`) |
|
|
||||||
| `paste` | Paste from clipboard to stdout |
|
|
||||||
|
|
||||||
### Terminal
|
|
||||||
|
|
||||||
| Function | Description |
|
|
||||||
|---|---|
|
|
||||||
| `split [-h\|-v] [cmd]` | Open a new split pane, optionally running a command |
|
|
||||||
| `spwin` | Spawn a new OS window |
|
|
||||||
| `detach <cmd>` | Run a command fully detached (`nohup`), no output |
|
|
||||||
| `bkg <cmd>` | Background a command, discarding all output |
|
|
||||||
|
|
||||||
### System
|
|
||||||
|
|
||||||
| Function | Description |
|
|
||||||
|---|---|
|
|
||||||
| `lock` | Lock the session via `loginctl lock-session` |
|
|
||||||
| `screensleep` | Turn off the display via KDE PowerDevil |
|
|
||||||
| `wake-lock <cmd>` | Run a command with `systemd-inhibit` to prevent sleep |
|
|
||||||
| `swapstat` | Colorized zRAM compression ratio, swappiness, and swap priority report |
|
|
||||||
| `tmux-clean` | Kill all detached tmux sessions |
|
|
||||||
| `limine-edit` | Safely edit and re-verify Limine bootloader configuration |
|
|
||||||
| `sbver` | Verify bootloader signing status for Secure Boot |
|
|
||||||
|
|
||||||
### Media & Utilities
|
|
||||||
|
|
||||||
| Function | Description |
|
|
||||||
|---|---|
|
|
||||||
| `dng2avif` | Convert DNG raw images to 10-bit HDR AVIF |
|
|
||||||
| `steam-dl` | Run Steam while inhibiting system sleep |
|
|
||||||
|
|
||||||
### Editors & Development
|
|
||||||
|
|
||||||
| Function | Description |
|
|
||||||
|---|---|
|
|
||||||
| `edit` / `e` | Open in Neovim (or `$EDITOR`) |
|
|
||||||
| `view` | Open in Neovim read-only mode |
|
|
||||||
| `fc` | Edit and execute the last command (Bash-style `fc`) |
|
|
||||||
| `nvimup` | Update Neovim headlessly |
|
|
||||||
| `nlazyup` | Sync Lazy.nvim plugins headlessly |
|
|
||||||
|
|
||||||
### AI Assistants
|
|
||||||
|
|
||||||
| Function | Description |
|
|
||||||
|---|---|
|
|
||||||
| `claude-resume` | Resume Claude Code session from `.claude_session` in CWD |
|
|
||||||
| `gemini-resume` | Resume Gemini CLI session from `.gemini_session` in CWD |
|
|
||||||
| `code-resume` | Smart resume — tries Claude then Gemini, falls back to picker |
|
|
||||||
| `superpowers [on\|off]` | Enable/disable the Superpowers extension for Claude and Gemini |
|
|
||||||
|
|
||||||
### Fetch & Info
|
|
||||||
|
|
||||||
| Function | Description |
|
|
||||||
|---|---|
|
|
||||||
| `ffetch` | Run fastfetch with `~/.fastfetch.jsonc` if present |
|
|
||||||
| `cffetch` | Clear screen then run fastfetch |
|
|
||||||
| `hist` | FZF history search — selected command is placed in the prompt and copied to clipboard |
|
|
||||||
| `qr <text>` | Generate a terminal QR code |
|
|
||||||
|
|
||||||
### Miscellaneous
|
|
||||||
|
|
||||||
| Function | Description |
|
|
||||||
|---|---|
|
|
||||||
| `upgrade` | System upgrade via paru |
|
|
||||||
| `zellij` | Zellij with `--theme catppuccin-mocha` |
|
|
||||||
| `antigravity` | Wrapper that suppresses a noisy deprecation warning |
|
|
||||||
| `bash` | Drop into bash (raw Fish session via `rawfish`) |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Abbreviations
|
## Documentation
|
||||||
|
|
||||||
Abbreviations expand in-place as you type, keeping your history clean.
|
### [📖 Documentation Site](https://fish.rootiest.fyi/)
|
||||||
|
|
||||||
### History Expansions (Bash-style)
|
A Starlight-powered site rebuilt on every push to `main`. It covers
|
||||||
|
configuration variables, key bindings, abbreviations, all functions, the
|
||||||
|
dependency catalog, customization, and more, with full-text search.
|
||||||
|
|
||||||
These abbreviations replicate Bash's bang-style history expansions. They expand anywhere in the command line when a trigger key (like `Space` or `Enter`) is pressed.
|
Contributing to the docs? There are two sources, split by content type:
|
||||||
|
|
||||||
| Abbr | Expansion | Description |
|
- **Function documentation** comes from the man-page-style comment header
|
||||||
|---|---|---|
|
above each function in `functions/*.fish`. Edit the function; the entry
|
||||||
| `!^` | First argument | Expands to the first argument of the previous command |
|
and its site page are generated from the header.
|
||||||
| `!*` | All arguments | Expands to all arguments of the previous command |
|
- **Everything else** lives under `docs/manual/**`.
|
||||||
| `!-n` | n-th previous | Expands to the n-th previous command in history (e.g., `!-2`) |
|
|
||||||
| `!string` | Prefix search | Expands to the most recent command starting with `string` |
|
|
||||||
| `!?string?` | Contains search | Expands to the most recent command containing `string` |
|
|
||||||
| `^old^new` | Quick substitution | Replaces `old` with `new` in the previous command and expands to it |
|
|
||||||
|
|
||||||
### Editors
|
Never edit the generated `docs/fish-config.md` — it's rebuilt from both
|
||||||
|
sources and any hand-edits are discarded.
|
||||||
|
|
||||||
| Abbr | Expands To |
|
To browse the docs from the terminal:
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `n`, `nv` | `nvim` |
|
| `help config` | Open the terminal manual in the best available pager |
|
||||||
| `e` | `edit` |
|
| `help config <keyword>` | Jump directly to a section matching the keyword |
|
||||||
| `se` | `sudoedit` |
|
| `help config --html` | Open the documentation site in the default browser |
|
||||||
| `v` | `antigravity` (VSCode-equivalent) |
|
| `help config --man` | Open the compiled man page via `man -l` |
|
||||||
| `k` | `kate` |
|
| `help config <keyword> --man` | Open the man page jumping to the nearest match |
|
||||||
|
| `repo-open` | Open this repo's web page in the browser (deep-links to the current branch and sub-directory) |
|
||||||
|
|
||||||
### Listing
|
The pager falls back through: **ov** → **bat** → **man -l** → **less** → **cat**.
|
||||||
|
|
||||||
| Abbr | Expands To |
|
> **Note:** `fish-config` (hyphen) is this configuration's man page. `fish_config` (underscore) is fish's built-in browser-based configuration tool — a completely separate command. Don't mix them up.
|
||||||
|---|---|
|
|
||||||
| `l` | `ls` |
|
|
||||||
| `lS` | `lss` (size-sorted) |
|
|
||||||
| `lsR` | `lsr` (reversed time) |
|
|
||||||
| `lX` | `lx` (extension-sorted) |
|
|
||||||
| `lT` | `lt` (tree, depth 2) |
|
|
||||||
| `lsT` | `lstree` (full tree) |
|
|
||||||
|
|
||||||
### Navigation
|
|
||||||
|
|
||||||
| Abbr | Expands To |
|
|
||||||
|---|---|
|
|
||||||
| `cdnv` | `cd ~/.config/nvim` |
|
|
||||||
| `:cdf` | `cd ~/.config/fish/` |
|
|
||||||
| `:cdk` | `cd ~/.config/kitty/` |
|
|
||||||
| `:cdh` | `cd ~` |
|
|
||||||
| `:cdp` | `cd ~/projects/` (with cursor placement) |
|
|
||||||
| `:cdcz` | `cd ~/.local/share/chezmoi/` |
|
|
||||||
|
|
||||||
### Git
|
|
||||||
|
|
||||||
| Abbr | Expands To |
|
|
||||||
|---|---|
|
|
||||||
| `g` | `git` |
|
|
||||||
| `lg` | `lazygit` |
|
|
||||||
|
|
||||||
### Chezmoi
|
|
||||||
|
|
||||||
| Abbr | Expands To |
|
|
||||||
|---|---|
|
|
||||||
| `cm` / `cz` | `chezmoi` |
|
|
||||||
| `cmcd` | `chezmoi cd` |
|
|
||||||
| `cme` | `chezmoi edit` |
|
|
||||||
| `cmad` | `chezmoi add` |
|
|
||||||
| `cmap` | `chezmoi apply` |
|
|
||||||
| `cmf` | `chezmoi forget` |
|
|
||||||
| `cmi` | `chezmoi init` |
|
|
||||||
|
|
||||||
### Kitty / WezTerm Window Management
|
|
||||||
|
|
||||||
These abbreviations mirror Vim/tmux ergonomics for managing terminal splits, tabs, and windows. They automatically detect whether you are using Kitty or WezTerm and execute the appropriate terminal CLI commands.
|
|
||||||
|
|
||||||
| Abbr | Action |
|
|
||||||
|---|---|
|
|
||||||
| `:q` | Close active pane |
|
|
||||||
| `:Q` | Close active tab |
|
|
||||||
| `:w` | New OS window |
|
|
||||||
| `:t` | New tab |
|
|
||||||
| `:wv` | Horizontal split |
|
|
||||||
| `:wh` | Vertical split |
|
|
||||||
| `:tp` / `:tn` | Navigate tabs left/right |
|
|
||||||
| `:tl "Title"` | Rename current tab |
|
|
||||||
| `:tgn` | New tab in `~/.config/nvim` |
|
|
||||||
| `:tgf` | New tab in `~/.config/fish` |
|
|
||||||
| `:tgp` | New tab in `~/projects` |
|
|
||||||
| `:tgr` | New root tab (`sudo -i`) |
|
|
||||||
|
|
||||||
### SSH
|
|
||||||
|
|
||||||
Machine-specific SSH abbreviations (e.g. `sshr`, `sshrt`) live in `~/.config/.user-dots/fish/local.fish`.
|
|
||||||
(See [Personalization](#personalization) for examples)
|
|
||||||
|
|
||||||
### Docker
|
|
||||||
|
|
||||||
| Abbr | Expands To |
|
|
||||||
|---|---|
|
|
||||||
| `dcl` | `docker context use default` |
|
|
||||||
| `dcls` | `docker context ls` |
|
|
||||||
| `lzd` | `ld` (LazyDocker) |
|
|
||||||
|
|
||||||
Named context shortcuts (e.g. `dcr`, `dck`) live in `~/.config/.user-dots/fish/local.fish`.
|
|
||||||
(See [Personalization](#personalization) for examples)
|
|
||||||
|
|
||||||
### Systemctl
|
|
||||||
|
|
||||||
| Abbr | Expands To |
|
|
||||||
|---|---|
|
|
||||||
| `sc` | `systemctl` |
|
|
||||||
| `ssc` | `sudo systemctl` |
|
|
||||||
| `scu` | `systemctl --user` |
|
|
||||||
| `st` | `systemctl status` |
|
|
||||||
| `scs` | `systemctl start` |
|
|
||||||
| `scr` | `systemctl restart` |
|
|
||||||
| `ssct` | `sudo systemctl status` |
|
|
||||||
| `sscs` | `sudo systemctl start` |
|
|
||||||
| `sscr` | `sudo systemctl restart` |
|
|
||||||
|
|
||||||
### Beads (bd)
|
|
||||||
|
|
||||||
| Abbr | Expands To |
|
|
||||||
|---|---|
|
|
||||||
| `bl` | `bd list` |
|
|
||||||
| `bs` | `bd sync` |
|
|
||||||
| `bC` | `bd create --title` |
|
|
||||||
| `bsh` | `bd show` |
|
|
||||||
| `lb` | `lazybeads` |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Dependencies
|
|
||||||
|
|
||||||
### Required
|
|
||||||
|
|
||||||
| Tool | Purpose |
|
|
||||||
|---|---|
|
|
||||||
| [Fish](https://fishshell.com/) | Shell |
|
|
||||||
| [Fisher](https://github.com/jorgebucaran/fisher) | Plugin manager |
|
|
||||||
| [Starship](https://starship.rs/) | Prompt |
|
|
||||||
| [fzf](https://github.com/junegunn/fzf) | Fuzzy finder |
|
|
||||||
| [zoxide](https://github.com/ajeetdsouza/zoxide) | Smart directory jumper |
|
|
||||||
| [direnv](https://direnv.net/) | Per-directory env loading |
|
|
||||||
| [paru](https://github.com/Morganamilo/paru) | AUR helper |
|
|
||||||
|
|
||||||
### Recommended
|
|
||||||
|
|
||||||
| Tool | Replaces |
|
|
||||||
|---|---|
|
|
||||||
| [eza](https://github.com/eza-community/eza) | `ls` (preferred) |
|
|
||||||
| [lsd](https://github.com/lsd-rs/lsd) | `ls` (fallback) |
|
|
||||||
| [bat](https://github.com/sharkdp/bat) | `cat` |
|
|
||||||
| [btop](https://github.com/aristocratsupply/btop) | `top` |
|
|
||||||
| [dust](https://github.com/bootandy/dust) | `du` (directories) |
|
|
||||||
| [duf](https://github.com/muesli/duf) | `du` (disks) |
|
|
||||||
| [prettyping](https://github.com/denilsonsa/prettyping) | `ping` |
|
|
||||||
| [most](https://www.jedsoft.org/most/) | `less` |
|
|
||||||
| [ripgrep](https://github.com/BurntSushi/ripgrep) | `grep` |
|
|
||||||
| [lazygit](https://github.com/jesseduffield/lazygit) | git TUI |
|
|
||||||
| [lazydocker](https://github.com/jesseduffield/lazydocker) | Docker TUI |
|
|
||||||
| [trash-cli](https://github.com/andreafrancia/trash-cli) | Safe `rm` |
|
|
||||||
| [Kitty](https://sw.kovidgoyal.net/kitty/) / [WezTerm](https://wezfurlong.org/wezterm/) | Terminal emulator |
|
|
||||||
| [WakaTime](https://wakatime.com/) | Activity tracking |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -495,20 +174,39 @@ mv ~/.config/fish ~/.config/fish.bak
|
|||||||
git clone https://git.rootiest.dev/rootiest/fish-config.git ~/.config/fish
|
git clone https://git.rootiest.dev/rootiest/fish-config.git ~/.config/fish
|
||||||
```
|
```
|
||||||
|
|
||||||
Then open a new Fish shell — Fisher and all plugins will be installed automatically on first launch, and the Catppuccin Mocha theme will be applied.
|
Then open a new Fish shell — Fisher will be installed automatically on first launch and the Catppuccin Mocha theme will be applied. All plugin functionality is bundled directly with this config and requires no additional installation.
|
||||||
|
|
||||||
A [chezmoi](https://www.chezmoi.io/) dotfile manager is also configured — secrets are sourced from `~/.config/.user-dots/fish/secrets.fish` and excluded from version control.
|
A [chezmoi](https://www.chezmoi.io/) dotfile manager is also configured — secrets are kept in a private overlay directory (see [Personalization](#personalization)) and excluded from version control.
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> `config.fish` ends with a `return` sentinel guard. Any lines appended **after** it by a tool's setup command will silently have no effect. Many tools (starship, zoxide, mise, etc.) offer a setup command that appends an `init | source` line to your `config.fish` — all integrations are managed through `conf.d/` files instead. If you add a new tool and its shell integration appears to do nothing, check whether its setup command appended an init line to the bottom of `config.fish` and create a `conf.d/<tool>.fish` file for it instead.
|
||||||
|
|
||||||
|
### Updating the Config
|
||||||
|
|
||||||
|
Pull the latest changes from upstream without needing a configured git remote:
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
|---|---|
|
||||||
|
| `config-update` | Fetch and apply the latest commits from upstream |
|
||||||
|
| `config-update --dry-run` | Preview available changes without applying them |
|
||||||
|
| `config-update --force` | Stash local changes, pull, then restore the stash |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Personalization
|
## Personalization
|
||||||
|
|
||||||
Sensitive credentials and machine-specific paths are kept out of version control via a secondary private directory at `~/.config/.user-dots/fish/`. Two files are sourced automatically by `config.fish` if they exist:
|
Sensitive credentials and machine-specific paths are kept out of version control via a private overlay directory. The path defaults to `~/.config/.user-dots/fish/` but can be changed by setting a universal variable:
|
||||||
|
|
||||||
|
```fish
|
||||||
|
set -U __fish_user_dots_path /path/to/your/dots/fish
|
||||||
|
```
|
||||||
|
|
||||||
|
`config.fish` sources `local.fish` from that directory. `local.fish` is responsible for sourcing its own `secrets.fish` companion:
|
||||||
|
|
||||||
```
|
```
|
||||||
~/.config/.user-dots/fish/
|
$__fish_user_dots_path/
|
||||||
├── secrets.fish # API keys, tokens, passwords, personal identifiers
|
├── secrets.fish # API keys, tokens, passwords, personal identifiers
|
||||||
└── local.fish # Machine-specific paths and environment variables
|
└── local.fish # Machine-specific paths, env vars, and sourcing secrets
|
||||||
```
|
```
|
||||||
|
|
||||||
### secrets.fish
|
### secrets.fish
|
||||||
@@ -541,12 +239,12 @@ Use this file for paths and variables that are specific to one machine — thing
|
|||||||
```fish
|
```fish
|
||||||
# ~/.config/.user-dots/fish/local.fish
|
# ~/.config/.user-dots/fish/local.fish
|
||||||
|
|
||||||
# Project root for quick cd
|
|
||||||
set -gx cdp /home/youruser/projects
|
|
||||||
|
|
||||||
# CDPATH — directories searched by cd
|
# CDPATH — directories searched by cd
|
||||||
set -gx CDPATH . /home/youruser/projects /home/youruser
|
set -gx CDPATH . /home/youruser/projects /home/youruser
|
||||||
|
|
||||||
|
# Path to your shared .gitignore boilerplate (used by `gi -b` / `gi` default)
|
||||||
|
set -gx GITIGNORE_BOILERPLATE ~/.config/git/gitignore_boilerplate
|
||||||
|
|
||||||
### SSH ###
|
### SSH ###
|
||||||
# Quick shortcuts to your own servers
|
# Quick shortcuts to your own servers
|
||||||
abbr -a sshr 'ssh you@your-server.local'
|
abbr -a sshr 'ssh you@your-server.local'
|
||||||
@@ -560,25 +258,70 @@ abbr -a dcw 'docker context use work-server'
|
|||||||
|
|
||||||
### How it works
|
### How it works
|
||||||
|
|
||||||
`config.fish` sources both files with an existence check so the public config works cleanly on any machine that doesn't have the private repo:
|
`config.fish` sources only `local.fish` with an existence check so the public config works cleanly on any machine without the private repo. `local.fish` is responsible for sourcing its own `secrets.fish`:
|
||||||
|
|
||||||
```fish
|
```fish
|
||||||
if test -f $HOME/.config/.user-dots/fish/secrets.fish
|
# config.fish resolves the path, then sources local.fish
|
||||||
source $HOME/.config/.user-dots/fish/secrets.fish
|
set -q __fish_user_dots_path
|
||||||
end
|
or set -l __fish_user_dots_path "$XDG_CONFIG_HOME/.user-dots/fish"
|
||||||
|
test -f "$__fish_user_dots_path/local.fish"
|
||||||
if test -f $HOME/.config/.user-dots/fish/local.fish
|
and source "$__fish_user_dots_path/local.fish"
|
||||||
source $HOME/.config/.user-dots/fish/local.fish
|
|
||||||
end
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For convenience, a git-ignored `user-dots` symlink in the fish config directory is pointed at `$__fish_user_dots_path` on startup, so the overlay can be browsed from `~/.config/fish/`. It is recreated if missing and repointed if the path variable changes. Creation is a C2 startup side-effect (`__fish_config_op_autoexec`); it only ever manages a symlink and never clobbers a real file or directory at that path.
|
||||||
|
|
||||||
|
To opt out, set `__fish_user_dots_symlink` to a falsy value (or toggle **Dots link** off on the **Paths** page of `config-settings`). Disabling it stops the symlink being generated and removes any existing one immediately — honoured regardless of the C2 master switch.
|
||||||
|
|
||||||
`fish_variables` (which fish auto-manages and may contain universal variable state) is excluded from this repo via `.gitignore`.
|
`fish_variables` (which fish auto-manages and may contain universal variable state) is excluded from this repo via `.gitignore`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Full Requirements
|
## Minimal Mode
|
||||||
|
|
||||||
For a complete, categorized list of all non-standard tools required or used by this configuration, see [requirements.md](requirements.md).
|
Everything opinionated in this config — command shadows, startup side-effects, key and environment overrides, terminal integrations, and the first-run greeting — is active by default but can be switched off. Logging (C5) is the exception: it is **opt-in**, off until you explicitly enable it.
|
||||||
|
|
||||||
|
> **The easy way — `config-settings`:** Run `config-settings` for an interactive TUI that manages settings across four pages — **Universal** and **Session** (the opinionated category toggles below, persistent or per-shell), **Sponge** (history-scrubbing: delay, exit codes, purge-on-exit, and extra sensitive variable names), and **Paths** (scrollback log dir, max files, and the user-dots path) — without typing a single variable name. Navigate with the arrow keys (or `h`/`j`/`k`/`l`); toggle rows step OFF ← DEFAULT → ON, value rows edit inline with `Enter` and clear with `←`. `Tab`/`Shift-Tab` cycle pages and `q` quits. Changes apply instantly. The panel auto-sizes to your terminal width (four tiers from 52- to 78-wide with a 6-column margin), centers itself horizontally, and redraws within ~0.3 s of a resize.
|
||||||
|
|
||||||
|
If you'd rather set them by hand, each category is controlled by a universal variable. Six category toggles and one master switch are available:
|
||||||
|
|
||||||
|
| Variable | Disables |
|
||||||
|
|---|---|
|
||||||
|
| `__fish_config_op_aliases` | Command shadows: `ls`→eza, `cat`→bat, `cd`→zoxide, `rm`→trash, `top`→btop, `edit`→multi-editor launcher, and friends; `grep`/`cp`/`mv`/`wget` flag injection |
|
||||||
|
| `__fish_config_op_autoexec` | Startup side-effects: Fisher bootstrap, theme apply, `paru`/`yay` wrapper generation, auto venv activation, WakaTime hook, auto-pull background fast-forward |
|
||||||
|
| `__fish_config_op_overrides` | Vi mode, `exit`→`smart_exit`, `$PAGER`/`$MANPAGER`/`$CDPATH`/`XDG`/`PATH`, bang-bang history expansion, autopair, puffer, Starship prompt, theme colors |
|
||||||
|
| `__fish_config_op_integrations` | Kitty/WezTerm window abbreviations, `done` notifications, `spwin`/`tab`/`split`, `hist`, `logs`, `upgrade`, WakaTime |
|
||||||
|
| `__fish_config_op_logging` | **Opt-in — off unless explicitly enabled.** Scrollback capture on exit, tmux `pipe-pane` pane logging, zellij `dump-screen` capture on exit, `paru`/`yay` AUR log wrappers, Kitty watcher capture (sentinel-file coordinated) |
|
||||||
|
| `__fish_config_op_greeting` | Per-session `fish_greeting` (suppresses distro greetings such as CachyOS fastfetch by overriding with an empty function); first-run welcome banner |
|
||||||
|
| `__fish_config_opinionated` | Master switch — disables all six categories at once (it is a master *off* switch; it cannot enable opt-in C5 logging) |
|
||||||
|
|
||||||
|
Set any of them to a falsy value (`0`, `false`, `no`, `off`, `n`) to disable; erase the variable to re-enable. An explicit per-category truthy value overrides a falsy master switch, so you can disable everything with `__fish_config_opinionated=0` and selectively re-enable individual categories:
|
||||||
|
|
||||||
|
```fish
|
||||||
|
# Plain shell: disable everything opinionated
|
||||||
|
set -U __fish_config_opinionated 0
|
||||||
|
|
||||||
|
# Or pick a single category, e.g. keep integrations but drop command shadows
|
||||||
|
set -U __fish_config_op_aliases off
|
||||||
|
|
||||||
|
# Minimal mode but keep the greeting (per-category overrides master)
|
||||||
|
set -U __fish_config_opinionated 0
|
||||||
|
set -U __fish_config_op_greeting 1
|
||||||
|
|
||||||
|
# Opt in to session logging (C5 is off by default)
|
||||||
|
set -U __fish_config_op_logging on
|
||||||
|
|
||||||
|
# Back to full flavor
|
||||||
|
set -Ue __fish_config_opinionated
|
||||||
|
set -Ue __fish_config_op_greeting
|
||||||
|
```
|
||||||
|
|
||||||
|
Command shadows react immediately; bindings, prompt, and abbreviations take effect in new shells. With aliases disabled, `rm` deletes permanently again instead of trashing. See `help config opinionated` for the full component list.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
The core of the [Zoxide integration](https://fish.rootiest.fyi/02-path-setup/) in this repository was originally adapted from the [icezyclon/zoxide.fish](https://github.com/icezyclon/zoxide.fish) plugin (MIT Licensed) and has since been heavily customized for performance and Fish 4.x compatibility.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
# Completions for the `auto-pull` registry command.
|
||||||
|
|
||||||
|
function __auto_pull_registered
|
||||||
|
set -l list "$XDG_CONFIG_HOME/.user-dots/fish/auto-pull.list"
|
||||||
|
test -r "$list"; or return
|
||||||
|
for l in (command cat "$list" 2>/dev/null)
|
||||||
|
test -n "$l"; or continue
|
||||||
|
printf '%s\t%s\n' (path basename "$l") "$l"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l subcmds list add remove status
|
||||||
|
|
||||||
|
# Subcommands (only as the first argument).
|
||||||
|
complete -c auto-pull -f -n "not __fish_seen_subcommand_from $subcmds" \
|
||||||
|
-a list -d 'Show registered repos'
|
||||||
|
complete -c auto-pull -f -n "not __fish_seen_subcommand_from $subcmds" \
|
||||||
|
-a add -d "Register a repo (default: current)"
|
||||||
|
complete -c auto-pull -f -n "not __fish_seen_subcommand_from $subcmds" \
|
||||||
|
-a remove -d 'Unregister a repo'
|
||||||
|
complete -c auto-pull -f -n "not __fish_seen_subcommand_from $subcmds" \
|
||||||
|
-a status -d 'Show enabled state and registry path'
|
||||||
|
complete -c auto-pull -f -n "not __fish_seen_subcommand_from $subcmds" \
|
||||||
|
-s h -l help -d 'Show help'
|
||||||
|
|
||||||
|
# `add` takes a directory path.
|
||||||
|
complete -c auto-pull -n "__fish_seen_subcommand_from add" -a '(__fish_complete_directories)'
|
||||||
|
|
||||||
|
# `remove` completes registered repo basenames.
|
||||||
|
complete -c auto-pull -f -n "__fish_seen_subcommand_from remove" -a '(__auto_pull_registered)'
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
# fish completion for copilot
|
||||||
|
# Generated by `copilot completion fish`. Do not edit by hand.
|
||||||
|
|
||||||
|
complete -c copilot -n '__fish_use_subcommand' -f -a 'login' -d 'Authenticate with Copilot'
|
||||||
|
complete -c copilot -n '__fish_use_subcommand' -f -a 'help' -d 'Display help information'
|
||||||
|
complete -c copilot -n '__fish_use_subcommand' -f -a 'init' -d 'Initialize Copilot instructions'
|
||||||
|
complete -c copilot -n '__fish_use_subcommand' -f -a 'update' -d 'Download the latest version'
|
||||||
|
complete -c copilot -n '__fish_use_subcommand' -f -a 'version' -d 'Display version information'
|
||||||
|
complete -c copilot -n '__fish_use_subcommand' -f -a 'plugin' -d 'Manage plugins'
|
||||||
|
complete -c copilot -n '__fish_use_subcommand' -f -a 'mcp' -d 'Manage MCP servers'
|
||||||
|
complete -c copilot -n '__fish_use_subcommand' -f -a 'completion' -d 'Generate a shell completion script'
|
||||||
|
complete -c copilot -l version -s v -f -d 'show version information'
|
||||||
|
complete -c copilot -l interactive -s i -r -d 'Start interactive mode and automatically execute this prompt'
|
||||||
|
complete -c copilot -l prompt -s p -r -d 'Execute a prompt in non-interactive mode (exits after completion)'
|
||||||
|
complete -c copilot -l silent -s s -f -d 'Output only the agent response (no stats), useful for scripting with -p'
|
||||||
|
complete -c copilot -l enable-memory -f -d 'Enable memory in prompt mode (disabled by default)'
|
||||||
|
complete -c copilot -l model -r -d 'Set the AI model to use (use \'auto\' to let Copilot pick automatically)'
|
||||||
|
complete -c copilot -l effort -l reasoning-effort -r -d 'Set the reasoning effort level' -a 'none low medium high xhigh max'
|
||||||
|
complete -c copilot -l context -r -d 'Set the context window tier (overrides persisted setting)' -a 'default long_context'
|
||||||
|
complete -c copilot -l enable-reasoning-summaries -f -d 'Request reasoning summaries for OpenAI models'
|
||||||
|
complete -c copilot -l agent -r -d 'Specify a custom agent to use'
|
||||||
|
complete -c copilot -l resume -s r -r -d 'Resume from a previous session (optionally specify existing session ID, task ID, ID prefix, or name; name matching is exact, case-insensitive)'
|
||||||
|
complete -c copilot -l continue -f -d 'Resume the most recent session'
|
||||||
|
complete -c copilot -l name -s n -r -d 'Set a name for the new session'
|
||||||
|
complete -c copilot -l session-id -r -d 'Resume an existing session or task by ID, or set the UUID for a new session'
|
||||||
|
complete -c copilot -l connect -r -d 'Connect directly to a remote session (optionally specify session ID or task ID)'
|
||||||
|
complete -c copilot -l allow-all-tools -f -d 'Allow all tools to run automatically without confirmation; required for non-interactive mode'
|
||||||
|
complete -c copilot -l allow-all-paths -f -d 'Disable file path verification and allow access to any path'
|
||||||
|
complete -c copilot -l disallow-temp-dir -f -d 'Prevent automatic access to the system temporary directory'
|
||||||
|
complete -c copilot -l no-custom-instructions -f -d 'Disable loading of custom instructions from AGENTS.md and related files'
|
||||||
|
complete -c copilot -l no-auto-update -f -d 'Disable downloading CLI update automatically (disabled by default in CI environments)'
|
||||||
|
complete -c copilot -l no-ask-user -f -d 'Disable the ask_user tool (agent works autonomously without asking questions)'
|
||||||
|
complete -c copilot -l banner -f -d 'Show the startup banner'
|
||||||
|
complete -c copilot -l no-color -f -d 'Disable all color output'
|
||||||
|
complete -c copilot -l screen-reader -f -d 'Enable screen reader optimizations'
|
||||||
|
complete -c copilot -l plain-diff -f -d 'Disable rich diff rendering (syntax highlighting via diff tool specified by git config)'
|
||||||
|
complete -c copilot -s C -r -d 'Change working directory before doing anything else'
|
||||||
|
complete -c copilot -l log-dir -r -d 'Set log file directory (default: ~/.copilot/logs/)'
|
||||||
|
complete -c copilot -l extension-sdk-path -r -d 'Override the bundled @github/copilot-sdk injected into extension subprocesses with a local `copilot-sdk/` folder. Invalid paths fall back to the bundled SDK.'
|
||||||
|
complete -c copilot -l log-level -r -d 'Set the log level' -a 'none error warning info debug all default'
|
||||||
|
complete -c copilot -l stream -r -d 'Enable or disable streaming mode' -a 'on off'
|
||||||
|
complete -c copilot -l output-format -r -d 'Output format: \'text\' (default) or \'json\' (JSONL, one JSON object per line)' -a 'text json'
|
||||||
|
complete -c copilot -l share -r -d 'Share session to markdown file after completion in non-interactive mode (default: ./copilot-session-<id>.md)'
|
||||||
|
complete -c copilot -l share-gist -f -d 'Share session to a secret GitHub gist after completion in non-interactive mode'
|
||||||
|
complete -c copilot -l add-dir -r -d 'Add a directory to the allowed list for file access (can be used multiple times)'
|
||||||
|
complete -c copilot -l attachment -r -d 'Attach a file (image or native document) to the initial prompt; only valid in non-interactive mode (can be used multiple times)'
|
||||||
|
complete -c copilot -l disable-mcp-server -r -d 'Disable a specific MCP server (can be used multiple times)'
|
||||||
|
complete -c copilot -l disable-builtin-mcps -f -d 'Disable all built-in MCP servers (currently: github-mcp-server)'
|
||||||
|
complete -c copilot -l enable-all-github-mcp-tools -f -d 'Enable all GitHub MCP server tools instead of the default CLI subset. Overrides --add-github-mcp-toolset and --add-github-mcp-tool options.'
|
||||||
|
complete -c copilot -l add-github-mcp-toolset -r -d 'Add a toolset to enable for the GitHub MCP server instead of the default CLI subset (can be used multiple times). Use "all" for all toolsets.'
|
||||||
|
complete -c copilot -l add-github-mcp-tool -r -d 'Add a tool to enable for the GitHub MCP server instead of the default CLI subset (can be used multiple times). Use "*" for all tools.'
|
||||||
|
complete -c copilot -l plugin-dir -r -d 'Load a plugin from a local directory (can be used multiple times)'
|
||||||
|
complete -c copilot -l additional-mcp-config -r -d 'Additional MCP servers configuration as JSON string or file path (prefix with @) (can be used multiple times; augments config from ~/.copilot/mcp-config.json for this session)'
|
||||||
|
complete -c copilot -l allow-tool -r -d 'Tools the CLI has permission to use; will not prompt for permission'
|
||||||
|
complete -c copilot -l deny-tool -r -d 'Tools the CLI does not have permission to use; will not prompt for permission'
|
||||||
|
complete -c copilot -l available-tools -r -d 'Only these tools will be available to the model'
|
||||||
|
complete -c copilot -l excluded-tools -r -d 'These tools will not be available to the model'
|
||||||
|
complete -c copilot -l secret-env-vars -r -d 'Environment variable names whose values are stripped from shell and MCP server environments and redacted from output (e.g., --secret-env-vars=MY_KEY,OTHER_KEY)'
|
||||||
|
complete -c copilot -l allow-url -r -d 'Allow access to specific URLs or domains'
|
||||||
|
complete -c copilot -l deny-url -r -d 'Deny access to specific URLs or domains, takes precedence over --allow-url'
|
||||||
|
complete -c copilot -l allow-all-urls -f -d 'Allow access to all URLs without confirmation'
|
||||||
|
complete -c copilot -l allow-all -f -d 'Enable all permissions (equivalent to --allow-all-tools --allow-all-paths --allow-all-urls)'
|
||||||
|
complete -c copilot -l yolo -f -d 'Enable all permissions (equivalent to --allow-all-tools --allow-all-paths --allow-all-urls)'
|
||||||
|
complete -c copilot -l max-autopilot-continues -r -d 'Maximum number of continuation messages in autopilot mode'
|
||||||
|
complete -c copilot -l mode -r -d 'Set the initial agent mode' -a 'interactive plan autopilot'
|
||||||
|
complete -c copilot -l autopilot -f -d 'Start in autopilot mode'
|
||||||
|
complete -c copilot -l plan -f -d 'Start in plan mode'
|
||||||
|
complete -c copilot -l experimental -f -d 'Enable experimental features'
|
||||||
|
complete -c copilot -l no-experimental -f -d 'Disable experimental features'
|
||||||
|
complete -c copilot -l bash-env -r -d 'Enable BASH_ENV support for bash shells (on|off)'
|
||||||
|
complete -c copilot -l no-bash-env -f -d 'Disable BASH_ENV support for bash shells'
|
||||||
|
complete -c copilot -l mouse -r -d 'Enable mouse support in alt screen mode (on|off)'
|
||||||
|
complete -c copilot -l no-mouse -f -d 'Disable mouse support in alt screen mode'
|
||||||
|
complete -c copilot -l acp -f -d 'Start as Agent Client Protocol server'
|
||||||
|
complete -c copilot -l remote -f -d 'Enable remote control of your session from GitHub web and mobile'
|
||||||
|
complete -c copilot -l no-remote -f -d 'Disable remote control of your session from GitHub web and mobile'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from login' -l host -r -d 'GitHub host URL (default: https://github.com)'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from plugin' -f -a 'install' -d 'Install a plugin'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from plugin' -f -a 'uninstall' -d 'Uninstall a plugin'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from plugin' -f -a 'update' -d 'Update a plugin'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from plugin' -f -a 'list' -d 'List installed plugins'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from plugin' -f -a 'marketplace' -d 'Manage plugin marketplaces'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from plugin; and __fish_seen_subcommand_from update' -l all -f -d 'Update all installed plugins'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from plugin; and __fish_seen_subcommand_from marketplace' -f -a 'add' -d 'Add a marketplace'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from plugin; and __fish_seen_subcommand_from marketplace' -f -a 'remove' -d 'Remove a marketplace'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from plugin; and __fish_seen_subcommand_from marketplace' -f -a 'list' -d 'List registered marketplaces'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from plugin; and __fish_seen_subcommand_from marketplace' -f -a 'browse' -d 'Browse plugins in a marketplace'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from plugin; and __fish_seen_subcommand_from marketplace' -f -a 'update' -d 'Update marketplace plugin catalogs'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from plugin; and __fish_seen_subcommand_from marketplace; and __fish_seen_subcommand_from remove' -l force -s f -f -d 'Force removal even if plugins are installed'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from mcp' -f -a 'list' -d 'List configured MCP servers'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from mcp' -f -a 'get' -d 'Show server details'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from mcp' -f -a 'add' -d 'Add an MCP server'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from mcp' -f -a 'remove' -d 'Remove an MCP server'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from list' -l json -f -d 'Output as JSON'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from get' -l json -f -d 'Output as JSON'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from get' -l show-secrets -f -d 'Show full environment variable and header values (masked by default)'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from add' -l transport -r -d 'Server transport' -a 'stdio http sse'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from add' -l env -r -d 'Environment variable (KEY=VALUE, can be repeated)'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from add' -l header -r -d 'HTTP header for remote servers, can be repeated'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from add' -l tools -r -d 'Tool filter: "*" for all, comma-separated list, or "" for none'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from add' -l timeout -r -d 'Timeout in milliseconds'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from add' -l json -f -d 'Output added config as JSON'
|
||||||
|
complete -c copilot -n '__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from add' -l show-secrets -f -d 'Show full environment variable and header values in output, masked by default'
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
# Completions for the `jobrunner` background job manager.
|
||||||
|
# `jr` inherits these via `function jr --wraps jobrunner`.
|
||||||
|
|
||||||
|
# Offer running jobs as name<TAB>description pairs.
|
||||||
|
function __jobrunner_complete_jobs
|
||||||
|
set -l tool ""
|
||||||
|
set -l tokens (commandline -opc)
|
||||||
|
set -l idx 1
|
||||||
|
while test $idx -le (count $tokens)
|
||||||
|
switch $tokens[$idx]
|
||||||
|
case -t --tool
|
||||||
|
set idx (math $idx + 1)
|
||||||
|
if test $idx -le (count $tokens)
|
||||||
|
set tool $tokens[$idx]
|
||||||
|
end
|
||||||
|
case '--tool=*'
|
||||||
|
set tool (string replace -- "--tool=" "" $tokens[$idx])
|
||||||
|
case '-t*'
|
||||||
|
set tool (string replace -r "^-t" "" $tokens[$idx])
|
||||||
|
end
|
||||||
|
set idx (math $idx + 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
for row in (__jobrunner_sessions $tool)
|
||||||
|
set -l f (string split \t -- $row)
|
||||||
|
printf '%s\t%s job (PID %s)\n' $f[1] $f[3] $f[2]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l subcmds run list attach kill logs help
|
||||||
|
set -l needs_job "__fish_seen_subcommand_from attach kill logs -a --attach -k --kill -o --output"
|
||||||
|
|
||||||
|
# No file completions; jobs are named, not paths.
|
||||||
|
complete -c jobrunner -f
|
||||||
|
|
||||||
|
# Backend tool selection flag.
|
||||||
|
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||||
|
-s t -l tool -x -a "tmux screen" -d 'Force specific backend'
|
||||||
|
|
||||||
|
# Subcommands (only as the first argument).
|
||||||
|
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||||
|
-a run -d 'Start a named job in the background'
|
||||||
|
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||||
|
-a list -d 'List all managed background jobs'
|
||||||
|
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||||
|
-a attach -d 'Re-attach interactively to a job'
|
||||||
|
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||||
|
-a kill -d 'Terminate a running background job'
|
||||||
|
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||||
|
-a logs -d "Print a job's output without attaching"
|
||||||
|
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||||
|
-a help -d 'Show usage help'
|
||||||
|
|
||||||
|
# Flag forms.
|
||||||
|
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||||
|
-s r -l run -d 'Start a named job in the background'
|
||||||
|
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||||
|
-s l -l list -d 'List all managed background jobs'
|
||||||
|
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||||
|
-s a -l attach -d 'Re-attach interactively to a job'
|
||||||
|
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||||
|
-s k -l kill -d 'Terminate a running background job'
|
||||||
|
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||||
|
-s o -l output -d "Print a job's output without attaching"
|
||||||
|
complete -c jobrunner -s h -l help -d 'Show usage help'
|
||||||
|
|
||||||
|
# Running jobs, for the subcommands that take one.
|
||||||
|
complete -c jobrunner -n "$needs_job" -a '(__jobrunner_complete_jobs)'
|
||||||
|
|
||||||
|
# A bare job name attaches to it, so offer jobs in first position too.
|
||||||
|
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||||
|
-a '(__jobrunner_complete_jobs)'
|
||||||
|
|
||||||
|
# After `run <name>`, complete the command to execute.
|
||||||
|
complete -c jobrunner -n "__fish_seen_subcommand_from run -r --run; and test (count (commandline -opc)) -ge 3" \
|
||||||
|
-a '(__fish_complete_subcommand)'
|
||||||
@@ -0,0 +1,235 @@
|
|||||||
|
# fish completion for ov -*- shell-script -*-
|
||||||
|
|
||||||
|
function __ov_debug
|
||||||
|
set -l file "$BASH_COMP_DEBUG_FILE"
|
||||||
|
if test -n "$file"
|
||||||
|
echo "$argv" >> $file
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function __ov_perform_completion
|
||||||
|
__ov_debug "Starting __ov_perform_completion"
|
||||||
|
|
||||||
|
# Extract all args except the last one
|
||||||
|
set -l args (commandline -opc)
|
||||||
|
# Extract the last arg and escape it in case it is a space
|
||||||
|
set -l lastArg (string escape -- (commandline -ct))
|
||||||
|
|
||||||
|
__ov_debug "args: $args"
|
||||||
|
__ov_debug "last arg: $lastArg"
|
||||||
|
|
||||||
|
# Disable ActiveHelp which is not supported for fish shell
|
||||||
|
set -l requestComp "OV_ACTIVE_HELP=0 $args[1] __complete $args[2..-1] $lastArg"
|
||||||
|
|
||||||
|
__ov_debug "Calling $requestComp"
|
||||||
|
set -l results (eval $requestComp 2> /dev/null)
|
||||||
|
|
||||||
|
# Some programs may output extra empty lines after the directive.
|
||||||
|
# Let's ignore them or else it will break completion.
|
||||||
|
# Ref: https://github.com/spf13/cobra/issues/1279
|
||||||
|
for line in $results[-1..1]
|
||||||
|
if test (string trim -- $line) = ""
|
||||||
|
# Found an empty line, remove it
|
||||||
|
set results $results[1..-2]
|
||||||
|
else
|
||||||
|
# Found non-empty line, we have our proper output
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l comps $results[1..-2]
|
||||||
|
set -l directiveLine $results[-1]
|
||||||
|
|
||||||
|
# For Fish, when completing a flag with an = (e.g., <program> -n=<TAB>)
|
||||||
|
# completions must be prefixed with the flag
|
||||||
|
set -l flagPrefix (string match -r -- '-.*=' "$lastArg")
|
||||||
|
|
||||||
|
__ov_debug "Comps: $comps"
|
||||||
|
__ov_debug "DirectiveLine: $directiveLine"
|
||||||
|
__ov_debug "flagPrefix: $flagPrefix"
|
||||||
|
|
||||||
|
for comp in $comps
|
||||||
|
printf "%s%s\n" "$flagPrefix" "$comp"
|
||||||
|
end
|
||||||
|
|
||||||
|
printf "%s\n" "$directiveLine"
|
||||||
|
end
|
||||||
|
|
||||||
|
# this function limits calls to __ov_perform_completion, by caching the result behind $__ov_perform_completion_once_result
|
||||||
|
function __ov_perform_completion_once
|
||||||
|
__ov_debug "Starting __ov_perform_completion_once"
|
||||||
|
|
||||||
|
if test -n "$__ov_perform_completion_once_result"
|
||||||
|
__ov_debug "Seems like a valid result already exists, skipping __ov_perform_completion"
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
set --global __ov_perform_completion_once_result (__ov_perform_completion)
|
||||||
|
if test -z "$__ov_perform_completion_once_result"
|
||||||
|
__ov_debug "No completions, probably due to a failure"
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
__ov_debug "Performed completions and set __ov_perform_completion_once_result"
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
# this function is used to clear the $__ov_perform_completion_once_result variable after completions are run
|
||||||
|
function __ov_clear_perform_completion_once_result
|
||||||
|
__ov_debug ""
|
||||||
|
__ov_debug "========= clearing previously set __ov_perform_completion_once_result variable =========="
|
||||||
|
set --erase __ov_perform_completion_once_result
|
||||||
|
__ov_debug "Successfully erased the variable __ov_perform_completion_once_result"
|
||||||
|
end
|
||||||
|
|
||||||
|
function __ov_requires_order_preservation
|
||||||
|
__ov_debug ""
|
||||||
|
__ov_debug "========= checking if order preservation is required =========="
|
||||||
|
|
||||||
|
__ov_perform_completion_once
|
||||||
|
if test -z "$__ov_perform_completion_once_result"
|
||||||
|
__ov_debug "Error determining if order preservation is required"
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l directive (string sub --start 2 $__ov_perform_completion_once_result[-1])
|
||||||
|
__ov_debug "Directive is: $directive"
|
||||||
|
|
||||||
|
set -l shellCompDirectiveKeepOrder 32
|
||||||
|
set -l keeporder (math (math --scale 0 $directive / $shellCompDirectiveKeepOrder) % 2)
|
||||||
|
__ov_debug "Keeporder is: $keeporder"
|
||||||
|
|
||||||
|
if test $keeporder -ne 0
|
||||||
|
__ov_debug "This does require order preservation"
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
__ov_debug "This doesn't require order preservation"
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# This function does two things:
|
||||||
|
# - Obtain the completions and store them in the global __ov_comp_results
|
||||||
|
# - Return false if file completion should be performed
|
||||||
|
function __ov_prepare_completions
|
||||||
|
__ov_debug ""
|
||||||
|
__ov_debug "========= starting completion logic =========="
|
||||||
|
|
||||||
|
# Start fresh
|
||||||
|
set --erase __ov_comp_results
|
||||||
|
|
||||||
|
__ov_perform_completion_once
|
||||||
|
__ov_debug "Completion results: $__ov_perform_completion_once_result"
|
||||||
|
|
||||||
|
if test -z "$__ov_perform_completion_once_result"
|
||||||
|
__ov_debug "No completion, probably due to a failure"
|
||||||
|
# Might as well do file completion, in case it helps
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l directive (string sub --start 2 $__ov_perform_completion_once_result[-1])
|
||||||
|
set --global __ov_comp_results $__ov_perform_completion_once_result[1..-2]
|
||||||
|
|
||||||
|
__ov_debug "Completions are: $__ov_comp_results"
|
||||||
|
__ov_debug "Directive is: $directive"
|
||||||
|
|
||||||
|
set -l shellCompDirectiveError 1
|
||||||
|
set -l shellCompDirectiveNoSpace 2
|
||||||
|
set -l shellCompDirectiveNoFileComp 4
|
||||||
|
set -l shellCompDirectiveFilterFileExt 8
|
||||||
|
set -l shellCompDirectiveFilterDirs 16
|
||||||
|
|
||||||
|
if test -z "$directive"
|
||||||
|
set directive 0
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l compErr (math (math --scale 0 $directive / $shellCompDirectiveError) % 2)
|
||||||
|
if test $compErr -eq 1
|
||||||
|
__ov_debug "Received error directive: aborting."
|
||||||
|
# Might as well do file completion, in case it helps
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l filefilter (math (math --scale 0 $directive / $shellCompDirectiveFilterFileExt) % 2)
|
||||||
|
set -l dirfilter (math (math --scale 0 $directive / $shellCompDirectiveFilterDirs) % 2)
|
||||||
|
if test $filefilter -eq 1; or test $dirfilter -eq 1
|
||||||
|
__ov_debug "File extension filtering or directory filtering not supported"
|
||||||
|
# Do full file completion instead
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l nospace (math (math --scale 0 $directive / $shellCompDirectiveNoSpace) % 2)
|
||||||
|
set -l nofiles (math (math --scale 0 $directive / $shellCompDirectiveNoFileComp) % 2)
|
||||||
|
|
||||||
|
__ov_debug "nospace: $nospace, nofiles: $nofiles"
|
||||||
|
|
||||||
|
# If we want to prevent a space, or if file completion is NOT disabled,
|
||||||
|
# we need to count the number of valid completions.
|
||||||
|
# To do so, we will filter on prefix as the completions we have received
|
||||||
|
# may not already be filtered so as to allow fish to match on different
|
||||||
|
# criteria than the prefix.
|
||||||
|
if test $nospace -ne 0; or test $nofiles -eq 0
|
||||||
|
set -l prefix (commandline -t | string escape --style=regex)
|
||||||
|
__ov_debug "prefix: $prefix"
|
||||||
|
|
||||||
|
set -l completions (string match -r -- "^$prefix.*" $__ov_comp_results)
|
||||||
|
set --global __ov_comp_results $completions
|
||||||
|
__ov_debug "Filtered completions are: $__ov_comp_results"
|
||||||
|
|
||||||
|
# Important not to quote the variable for count to work
|
||||||
|
set -l numComps (count $__ov_comp_results)
|
||||||
|
__ov_debug "numComps: $numComps"
|
||||||
|
|
||||||
|
if test $numComps -eq 1; and test $nospace -ne 0
|
||||||
|
# We must first split on \t to get rid of the descriptions to be
|
||||||
|
# able to check what the actual completion will be.
|
||||||
|
# We don't need descriptions anyway since there is only a single
|
||||||
|
# real completion which the shell will expand immediately.
|
||||||
|
set -l split (string split --max 1 \t $__ov_comp_results[1])
|
||||||
|
|
||||||
|
# Fish won't add a space if the completion ends with any
|
||||||
|
# of the following characters: @=/:.,
|
||||||
|
set -l lastChar (string sub -s -1 -- $split)
|
||||||
|
if not string match -r -q "[@=/:.,]" -- "$lastChar"
|
||||||
|
# In other cases, to support the "nospace" directive we trick the shell
|
||||||
|
# by outputting an extra, longer completion.
|
||||||
|
__ov_debug "Adding second completion to perform nospace directive"
|
||||||
|
set --global __ov_comp_results $split[1] $split[1].
|
||||||
|
__ov_debug "Completions are now: $__ov_comp_results"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if test $numComps -eq 0; and test $nofiles -eq 0
|
||||||
|
# To be consistent with bash and zsh, we only trigger file
|
||||||
|
# completion when there are no other completions
|
||||||
|
__ov_debug "Requesting file completion"
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
# Since Fish completions are only loaded once the user triggers them, we trigger them ourselves
|
||||||
|
# so we can properly delete any completions provided by another script.
|
||||||
|
# Only do this if the program can be found, or else fish may print some errors; besides,
|
||||||
|
# the existing completions will only be loaded if the program can be found.
|
||||||
|
if type -q "ov"
|
||||||
|
# The space after the program name is essential to trigger completion for the program
|
||||||
|
# and not completion of the program name itself.
|
||||||
|
# Also, we use '> /dev/null 2>&1' since '&>' is not supported in older versions of fish.
|
||||||
|
complete --do-complete "ov " > /dev/null 2>&1
|
||||||
|
end
|
||||||
|
|
||||||
|
# Remove any pre-existing completions for the program since we will be handling all of them.
|
||||||
|
complete -c ov -e
|
||||||
|
|
||||||
|
# this will get called after the two calls below and clear the $__ov_perform_completion_once_result global
|
||||||
|
complete -c ov -n '__ov_clear_perform_completion_once_result'
|
||||||
|
# The call to __ov_prepare_completions will setup __ov_comp_results
|
||||||
|
# which provides the program's completion choices.
|
||||||
|
# If this doesn't require order preservation, we don't use the -k flag
|
||||||
|
complete -c ov -n 'not __ov_requires_order_preservation && __ov_prepare_completions' -f -a '$__ov_comp_results'
|
||||||
|
# otherwise we use the -k flag
|
||||||
|
complete -k -c ov -n '__ov_requires_order_preservation && __ov_prepare_completions' -f -a '$__ov_comp_results'
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
complete -c rand_string -f
|
||||||
|
|
||||||
|
complete -c rand_string -s s -l separator -x -a 'dash underscore dot none' -d 'Set separator for following words'
|
||||||
|
complete -c rand_string -s c -l case -x -a 'lower upper title' -d 'Set casing for following words'
|
||||||
|
complete -c rand_string -s h -l help -d 'Show usage help'
|
||||||
|
|
||||||
|
# List of all available lists in data/words
|
||||||
|
set -l categories
|
||||||
|
if set -q __fish_config_dir
|
||||||
|
set categories (string replace -r '\.txt$' '' (command ls $__fish_config_dir/data/words/*.txt 2>/dev/null | command xargs -n 1 basename 2>/dev/null))
|
||||||
|
end
|
||||||
|
|
||||||
|
for cat in $categories
|
||||||
|
complete -c rand_string -a "$cat" -d "Pick a random word from the $cat list"
|
||||||
|
end
|
||||||
|
|
||||||
|
complete -c rand_string -a 'digits=' -d 'Generate N random digits (e.g. digits=3)'
|
||||||
|
complete -c rand_string -a 'literal=' -d 'Insert a literal string exactly as provided'
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
# Sourced from icezyclon/zoxide.fish (MIT)
|
||||||
|
|
||||||
|
set -l commands add help import init query remove
|
||||||
|
|
||||||
|
# disable normal all-files completion
|
||||||
|
complete -c zoxide -f
|
||||||
|
|
||||||
|
# onyl show base options if none was used already
|
||||||
|
complete -c zoxide -n __fish_use_subcommand -a add -d "Add a new directory or increment its rank"
|
||||||
|
complete -c zoxide -n __fish_use_subcommand -a help -d "Prints this message or the help of the given subcommand(s)"
|
||||||
|
complete -c zoxide -n __fish_use_subcommand -a import -d "Import from z database"
|
||||||
|
complete -c zoxide -n __fish_use_subcommand -a init -d "Generates shell configuration"
|
||||||
|
complete -c zoxide -n __fish_use_subcommand -a query -d "Search for a directory"
|
||||||
|
complete -c zoxide -n __fish_use_subcommand -a remove -d "Remove a directory"
|
||||||
|
|
||||||
|
# zoxide add
|
||||||
|
complete -c zoxide -n "_zoxide_equals_first_token add" -n "__fish_is_nth_token 2" -a "(__fish_complete_directories)"
|
||||||
|
|
||||||
|
# zoxide help
|
||||||
|
complete -c zoxide -n "_zoxide_equals_first_token help" -n "__fish_is_nth_token 2" -a "$commands"
|
||||||
|
|
||||||
|
# zoxide import
|
||||||
|
complete -c zoxide -r -F -n "_zoxide_equals_first_token import" -n "__fish_is_nth_token 2"
|
||||||
|
complete -c zoxide -r -n "_zoxide_equals_first_token import" -l merge -d "Merge entries into existing database"
|
||||||
|
|
||||||
|
# zoxide init
|
||||||
|
set -l initshells bash fish posix powershell zsh
|
||||||
|
complete -c zoxide -n "_zoxide_equals_first_token init" -n "__fish_is_nth_token 2" -a "$initshells"
|
||||||
|
complete -c zoxide -n "_zoxide_equals_first_token init" -l cmd -d "Renames the 'z' command and corresponding aliases [default: z]"
|
||||||
|
complete -c zoxide -n "_zoxide_equals_first_token init" -l hook -a "none prompt pwd" -d "Chooses event on which an entry is added to the database [default: pwd]"
|
||||||
|
complete -c zoxide -n "_zoxide_equals_first_token init" -l no-aliases -d "Prevents zoxide from defining any commands other than 'z'"
|
||||||
|
|
||||||
|
# zoxide query
|
||||||
|
complete -c zoxide -r -n "_zoxide_equals_first_token query" -s i -l interactive -d "Opens an interactive selection menu using fzf"
|
||||||
|
complete -c zoxide -r -n "_zoxide_equals_first_token query" -s l -l list -d "List all matching directories"
|
||||||
|
complete -c zoxide -r -n "_zoxide_equals_first_token query" -s s -l score -d "Display score along with result"
|
||||||
|
|
||||||
|
# zoxide remove
|
||||||
|
complete -c zoxide -n "_zoxide_equals_first_token remove" -n "__fish_is_nth_token 2" -a "(zoxide query -l)"
|
||||||
|
|
||||||
|
# Always possible
|
||||||
|
complete -c zoxide -x -s h -l help -d "Prints help information"
|
||||||
|
complete -c zoxide -x -s V -l version -d "Prints version information"
|
||||||
+568
-183
@@ -9,301 +9,686 @@
|
|||||||
# It is sourced by Fish on startup.
|
# It is sourced by Fish on startup.
|
||||||
|
|
||||||
# Neovim
|
# Neovim
|
||||||
|
# @category Editors
|
||||||
|
# @desc nvim
|
||||||
abbr -a n nvim
|
abbr -a n nvim
|
||||||
|
# @category Editors
|
||||||
|
# @desc nvim
|
||||||
abbr -a nv nvim
|
abbr -a nv nvim
|
||||||
|
# @category Editors
|
||||||
|
# @desc nvim
|
||||||
abbr -a neovim nvim
|
abbr -a neovim nvim
|
||||||
|
# @category Editors
|
||||||
|
# @desc cd ~/.config/nvim
|
||||||
abbr -a cdnv 'cd ~/.config/nvim # Neovim Config'
|
abbr -a cdnv 'cd ~/.config/nvim # Neovim Config'
|
||||||
|
# @category Editors
|
||||||
|
# @desc cd ~/.config/nvim; nvim
|
||||||
abbr -a cdnvn 'cd ~/.config/nvim;nvim'
|
abbr -a cdnvn 'cd ~/.config/nvim;nvim'
|
||||||
# VSCode
|
# VSCode
|
||||||
abbr -a v antigravity
|
# @category AI Assistants
|
||||||
|
# @desc antigravity-ide
|
||||||
|
abbr -a v antigravity-ide
|
||||||
# Kate
|
# Kate
|
||||||
|
# @category Editors
|
||||||
|
# @desc kate
|
||||||
abbr -a k kate
|
abbr -a k kate
|
||||||
# WezTerm SSH
|
# WezTerm SSH
|
||||||
if test "$TERM_PROGRAM" = WezTerm
|
if test "$TERM_PROGRAM" = WezTerm
|
||||||
|
# @category AI Assistants
|
||||||
|
# @desc wezterm ssh (WezTerm only)
|
||||||
abbr -a s wezterm ssh
|
abbr -a s wezterm ssh
|
||||||
end
|
end
|
||||||
# Neovim in a new tab
|
# Neovim in a new tab
|
||||||
if test "$TERM" = xterm-kitty
|
if test "$TERM" = xterm-kitty
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Open new tab with nvim (terminal-aware)
|
||||||
abbr -a editt kitty @ launch --type=tab --cwd=current nvim # Kitty
|
abbr -a editt kitty @ launch --type=tab --cwd=current nvim # Kitty
|
||||||
end
|
end
|
||||||
if test "$TERM_PROGRAM" = WezTerm
|
if test "$TERM_PROGRAM" = WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Open new tab with nvim (terminal-aware)
|
||||||
abbr -a editt wezterm cli spawn nvim # WezTerm
|
abbr -a editt wezterm cli spawn nvim # WezTerm
|
||||||
end
|
end
|
||||||
# LazyGit
|
# LazyGit
|
||||||
|
# @category Git
|
||||||
|
# @desc lazygit
|
||||||
abbr -a lg lazygit
|
abbr -a lg lazygit
|
||||||
# Sudo shell
|
# Sudo shell
|
||||||
|
# @category Miscellaneous
|
||||||
|
# @desc sudo -s
|
||||||
abbr -a sudu sudo -s
|
abbr -a sudu sudo -s
|
||||||
# Kitty
|
# Kitty
|
||||||
if test "$TERM" = xterm-kitty
|
if test "$TERM" = xterm-kitty
|
||||||
|
# @category Miscellaneous
|
||||||
|
# @desc kitty (Kitty only)
|
||||||
abbr -a kt kitty
|
abbr -a kt kitty
|
||||||
end
|
end
|
||||||
# cat
|
# cat
|
||||||
|
# @category Miscellaneous
|
||||||
|
# @desc cat
|
||||||
abbr -a c cat
|
abbr -a c cat
|
||||||
# chezmoi
|
# chezmoi
|
||||||
|
# @category Chezmoi
|
||||||
|
# @desc chezmoi
|
||||||
abbr -a cm chezmoi
|
abbr -a cm chezmoi
|
||||||
# chezmoi cd
|
# chezmoi cd
|
||||||
|
# @category Chezmoi
|
||||||
|
# @desc chezmoi cd
|
||||||
abbr -a cmcd chezmoi cd
|
abbr -a cmcd chezmoi cd
|
||||||
|
# @category Chezmoi
|
||||||
|
# @desc chezmoi cd
|
||||||
abbr -a czcd chezmoi cd
|
abbr -a czcd chezmoi cd
|
||||||
|
# @category Chezmoi
|
||||||
|
# @desc chezmoi cd
|
||||||
abbr -a cdcm chezmoi cd
|
abbr -a cdcm chezmoi cd
|
||||||
|
# @category Chezmoi
|
||||||
|
# @desc chezmoi cd
|
||||||
abbr -a cdcz chezmoi cd
|
abbr -a cdcz chezmoi cd
|
||||||
# chezmoi edit
|
# chezmoi edit
|
||||||
|
# @category Chezmoi
|
||||||
|
# @desc chezmoi edit
|
||||||
abbr -a cme chezmoi edit
|
abbr -a cme chezmoi edit
|
||||||
|
# @category Chezmoi
|
||||||
|
# @desc chezmoi edit
|
||||||
abbr -a cze chezmoi edit
|
abbr -a cze chezmoi edit
|
||||||
# chezmoi add
|
# chezmoi add
|
||||||
|
# @category Chezmoi
|
||||||
|
# @desc chezmoi add
|
||||||
abbr -a cmad chezmoi add
|
abbr -a cmad chezmoi add
|
||||||
|
# @category Chezmoi
|
||||||
|
# @desc chezmoi add
|
||||||
abbr -a czad chezmoi add
|
abbr -a czad chezmoi add
|
||||||
# chezmoi apply
|
# chezmoi apply
|
||||||
|
# @category Chezmoi
|
||||||
|
# @desc chezmoi apply
|
||||||
abbr -a cmap chezmoi apply
|
abbr -a cmap chezmoi apply
|
||||||
|
# @category Chezmoi
|
||||||
|
# @desc chezmoi apply
|
||||||
abbr -a czap chezmoi apply
|
abbr -a czap chezmoi apply
|
||||||
# chezmoi rm
|
# chezmoi rm
|
||||||
|
# @category Chezmoi
|
||||||
|
# @desc chezmoi forget
|
||||||
abbr -a cmrm chezmoi forget
|
abbr -a cmrm chezmoi forget
|
||||||
|
# @category Chezmoi
|
||||||
|
# @desc chezmoi forget
|
||||||
abbr -a cmf chezmoi forget
|
abbr -a cmf chezmoi forget
|
||||||
|
# @category Chezmoi
|
||||||
|
# @desc chezmoi forget
|
||||||
abbr -a czrm chezmoi forget
|
abbr -a czrm chezmoi forget
|
||||||
|
# @category Chezmoi
|
||||||
|
# @desc chezmoi forget
|
||||||
abbr -a czf chezmoi forget
|
abbr -a czf chezmoi forget
|
||||||
# chezmoi init
|
# chezmoi init
|
||||||
|
# @category Chezmoi
|
||||||
|
# @desc chezmoi init
|
||||||
abbr -a cmi chezmoi init
|
abbr -a cmi chezmoi init
|
||||||
|
# @category Chezmoi
|
||||||
|
# @desc chezmoi init
|
||||||
abbr -a czi chezmoi init
|
abbr -a czi chezmoi init
|
||||||
# Edit
|
# Edit
|
||||||
|
# @category Editors
|
||||||
|
# @desc edit
|
||||||
abbr -a e edit
|
abbr -a e edit
|
||||||
# Sudoedit
|
# Sudoedit
|
||||||
|
# @category Editors
|
||||||
|
# @desc sudoedit
|
||||||
abbr -a se sudoedit
|
abbr -a se sudoedit
|
||||||
# Git
|
# Git
|
||||||
|
# @category Git
|
||||||
|
# @desc git
|
||||||
abbr -a g git
|
abbr -a g git
|
||||||
|
# @category Git
|
||||||
|
# @desc generate .gitignore
|
||||||
|
abbr -a gitig gi
|
||||||
|
# @category Git
|
||||||
|
# @desc generate .gitignore
|
||||||
|
abbr -a git-ignore gi
|
||||||
# Antigravity
|
# Antigravity
|
||||||
abbr -a ag antigravity
|
# @category AI Assistants
|
||||||
abbr -a ag. antigravity .
|
# @desc agy
|
||||||
|
abbr -a ag agy
|
||||||
|
# @category AI Assistants
|
||||||
|
# @desc agy .
|
||||||
|
abbr -a ag. agy .
|
||||||
# Quit
|
# Quit
|
||||||
if test "$TERM" = xterm-kitty
|
# @category Miscellaneous
|
||||||
abbr -a :q kitty @ close-window # Kitty (Closes the active split/pane)
|
# @desc exit
|
||||||
abbr -a :Q kitty @ close-tab # Kitty (Closes the whole tab)
|
abbr -a /exit exit
|
||||||
end
|
# Window-management abbreviations are opinionated (C4 integrations)
|
||||||
if test "$TERM_PROGRAM" = WezTerm
|
if __fish_config_op_enabled __fish_config_op_integrations
|
||||||
abbr -a :q wezterm cli kill-pane # WezTerm
|
if test "$TERM" = xterm-kitty
|
||||||
abbr -a :Q wezterm cli kill-pane # WezTerm
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Close current pane/window
|
||||||
|
abbr -a :q kitty @ close-window # Kitty (Closes the active split/pane)
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Close current tab
|
||||||
|
abbr -a :Q kitty @ close-tab # Kitty (Closes the whole tab)
|
||||||
|
end
|
||||||
|
if test "$TERM_PROGRAM" = WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Close current pane/window
|
||||||
|
abbr -a :q wezterm cli kill-pane # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Close current tab
|
||||||
|
abbr -a :Q wezterm cli kill-pane # WezTerm
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
######### Alternates ##########
|
######### Alternates ##########
|
||||||
### ls alternates
|
### ls alternates
|
||||||
# List all files
|
# List all files
|
||||||
|
# @category Navigation and Listing
|
||||||
|
# @desc ls
|
||||||
abbr -a l ls
|
abbr -a l ls
|
||||||
# List all files by size
|
# List all files by size
|
||||||
|
# @category Navigation and Listing
|
||||||
|
# @desc lss (sort by size)
|
||||||
abbr -a lS lss
|
abbr -a lS lss
|
||||||
# List all files by reverse modified time
|
# List all files by reverse modified time
|
||||||
|
# @category Navigation and Listing
|
||||||
|
# @desc lsr (sort by time, oldest first)
|
||||||
abbr -a lsR lsr
|
abbr -a lsR lsr
|
||||||
# List by extension
|
# List by extension
|
||||||
|
# @category Navigation and Listing
|
||||||
|
# @desc lx (sort by extension)
|
||||||
abbr -a lX lx
|
abbr -a lX lx
|
||||||
# Tree listing (depth 2)
|
# Tree listing (depth 2)
|
||||||
|
# @category Navigation and Listing
|
||||||
|
# @desc lt (tree, depth 2)
|
||||||
abbr -a lT lt
|
abbr -a lT lt
|
||||||
# Full tree listing
|
# Full tree listing
|
||||||
|
# @category Navigation and Listing
|
||||||
|
# @desc lstree (full recursive tree)
|
||||||
abbr -a lsT lstree
|
abbr -a lsT lstree
|
||||||
|
### speed-test alternates
|
||||||
|
# Speedtest using fast.com
|
||||||
|
# @category Miscellaneous
|
||||||
|
# @desc fast-cli
|
||||||
|
abbr -a speedtest-fast fast-cli
|
||||||
|
|
||||||
# Window Creation (OS Windows)
|
# Kitty/WezTerm window-management abbreviations are opinionated (C4
|
||||||
if test "$TERM" = xterm-kitty
|
# integrations): they assume an active Kitty or WezTerm session.
|
||||||
abbr -a :w kitty @ launch --type=os-window # Kitty
|
if __fish_config_op_enabled __fish_config_op_integrations
|
||||||
end
|
# Window Creation (OS Windows)
|
||||||
if test "$TERM_PROGRAM" = WezTerm
|
if test "$TERM" = xterm-kitty
|
||||||
abbr -a :w wezterm cli spawn --new-window # WezTerm
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
end
|
# @desc New OS window
|
||||||
|
abbr -a :w kitty @ launch --type=os-window # Kitty
|
||||||
|
end
|
||||||
|
if test "$TERM_PROGRAM" = WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New OS window
|
||||||
|
abbr -a :w wezterm cli spawn --new-window # WezTerm
|
||||||
|
end
|
||||||
|
|
||||||
# Window Splits (Panes)
|
# Window Splits (Panes)
|
||||||
if test "$TERM" = xterm-kitty
|
if test "$TERM" = xterm-kitty
|
||||||
abbr -a :wv kitty @ launch --location=hsplit # Kitty (Horizontal split)
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :wh kitty @ launch --location=vsplit # Kitty (Vertical split)
|
# @desc Split pane horizontally (new pane below)
|
||||||
end
|
abbr -a :wv kitty @ launch --location=hsplit # Kitty (Horizontal split)
|
||||||
if test "$TERM_PROGRAM" = WezTerm
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :wv wezterm cli split-pane --bottom # WezTerm
|
# @desc Split pane vertically (new pane to the right)
|
||||||
abbr -a :wh wezterm cli split-pane --right # WezTerm
|
abbr -a :wh kitty @ launch --location=vsplit # Kitty (Vertical split)
|
||||||
end
|
end
|
||||||
|
if test "$TERM_PROGRAM" = WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Split pane horizontally (new pane below)
|
||||||
|
abbr -a :wv wezterm cli split-pane --bottom # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Split pane vertically (new pane to the right)
|
||||||
|
abbr -a :wh wezterm cli split-pane --right # WezTerm
|
||||||
|
end
|
||||||
|
|
||||||
# Window Detach (Move Pane)
|
# Window Detach (Move Pane)
|
||||||
if test "$TERM" = xterm-kitty
|
if test "$TERM" = xterm-kitty
|
||||||
abbr -a :wo kitty @ detach-window --target-tab=new # Kitty (Moves pane to new tab)
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :wot kitty @ detach-window # Kitty (Same as above, default behavior)
|
# @desc Detach current window to its own OS window
|
||||||
end
|
abbr -a :wo kitty @ detach-window --target-tab=new # Kitty (Moves pane to new tab)
|
||||||
if test "$TERM_PROGRAM" = WezTerm
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :wo wezterm cli move-pane-to-new-tab --new-window # WezTerm
|
# @desc Move current pane to a new tab
|
||||||
abbr -a :wot wezterm cli move-pane-to-new-tab # WezTerm
|
abbr -a :wot kitty @ detach-window # Kitty (Same as above, default behavior)
|
||||||
end
|
end
|
||||||
|
if test "$TERM_PROGRAM" = WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Detach current window to its own OS window
|
||||||
|
abbr -a :wo wezterm cli move-pane-to-new-tab --new-window # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Move current pane to a new tab
|
||||||
|
abbr -a :wot wezterm cli move-pane-to-new-tab # WezTerm
|
||||||
|
end
|
||||||
|
|
||||||
# Tab Creation
|
# Tab Creation
|
||||||
if test "$TERM" = xterm-kitty
|
if test "$TERM" = xterm-kitty
|
||||||
abbr -a :t kitty @ launch --type=tab # Kitty
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
end
|
# @desc New tab
|
||||||
if test "$TERM_PROGRAM" = WezTerm
|
abbr -a :t kitty @ launch --type=tab # Kitty
|
||||||
abbr -a :t wezterm cli spawn # WezTerm
|
end
|
||||||
end
|
if test "$TERM_PROGRAM" = WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New tab
|
||||||
|
abbr -a :t wezterm cli spawn # WezTerm
|
||||||
|
end
|
||||||
|
|
||||||
# Rename Tab
|
# Rename Tab
|
||||||
if test "$TERM" = xterm-kitty
|
if test "$TERM" = xterm-kitty
|
||||||
abbr -a :tl "kitty @ set-tab-title" # Kitty -> Usage: :tl "New Title"
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
end
|
# @desc Set tab title
|
||||||
if test "$TERM_PROGRAM" = WezTerm
|
abbr -a :tl "kitty @ set-tab-title" # Kitty -> Usage: :tl "New Title"
|
||||||
abbr -a :tl wezterm cli set-tab-title # WezTerm
|
end
|
||||||
end
|
if test "$TERM_PROGRAM" = WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Set tab title
|
||||||
|
abbr -a :tl wezterm cli set-tab-title # WezTerm
|
||||||
|
end
|
||||||
|
|
||||||
# Rename Window
|
# Rename Window
|
||||||
if test "$TERM" = xterm-kitty
|
if test "$TERM" = xterm-kitty
|
||||||
abbr -a :tw "kitty @ set-window-title" # Kitty
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
end
|
# @desc Set window title
|
||||||
if test "$TERM_PROGRAM" = WezTerm
|
abbr -a :tw "kitty @ set-window-title" # Kitty
|
||||||
abbr -a :tw wezterm cli set-window-title # WezTerm
|
end
|
||||||
end
|
if test "$TERM_PROGRAM" = WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Set window title
|
||||||
|
abbr -a :tw wezterm cli set-window-title # WezTerm
|
||||||
|
end
|
||||||
|
|
||||||
# Rename Workspace
|
# Rename Workspace
|
||||||
if test "$TERM_PROGRAM" = WezTerm
|
if test "$TERM_PROGRAM" = WezTerm
|
||||||
abbr -a :twk wezterm cli rename-workspace # WezTerm
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
end
|
# @desc Rename workspace (WezTerm only)
|
||||||
# Kitty does not have a direct CLI equivalent for renaming a dynamic "workspace" session.
|
abbr -a :twk wezterm cli rename-workspace # WezTerm
|
||||||
|
end
|
||||||
|
# Kitty does not have a direct CLI equivalent for renaming a dynamic "workspace" session.
|
||||||
|
|
||||||
# Tab Navigation
|
# Tab Navigation
|
||||||
if test "$TERM" = xterm-kitty
|
if test "$TERM" = xterm-kitty
|
||||||
abbr -a :tp "kitty @ focus-tab --match neighbor:left" # Kitty
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :tn "kitty @ focus-tab --match neighbor:right" # Kitty
|
# @desc Focus previous tab
|
||||||
end
|
abbr -a :tp "kitty @ focus-tab --match neighbor:left" # Kitty
|
||||||
if test "$TERM_PROGRAM" = WezTerm
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :tp wezterm cli activate-tab --tab-relative -1 # WezTerm
|
# @desc Focus next tab
|
||||||
abbr -a :tn wezterm cli activate-tab --tab-relative 1 # WezTerm
|
abbr -a :tn "kitty @ focus-tab --match neighbor:right" # Kitty
|
||||||
end
|
end
|
||||||
|
if test "$TERM_PROGRAM" = WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Focus previous tab
|
||||||
|
abbr -a :tp wezterm cli activate-tab --tab-relative -1 # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Focus next tab
|
||||||
|
abbr -a :tn wezterm cli activate-tab --tab-relative 1 # WezTerm
|
||||||
|
end
|
||||||
|
|
||||||
# Specialty Tab Shortcuts (New Tab in specific dir)
|
# Specialty Tab Shortcuts (New Tab in specific dir)
|
||||||
if test "$TERM" = xterm-kitty
|
if test "$TERM" = xterm-kitty
|
||||||
abbr -a :tgk kitty @ launch --type=tab --cwd ~/.config/kitty # Kitty
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :tgn kitty @ launch --type=tab --cwd ~/.config/nvim # Kitty
|
# @desc New tab at ~/.config/kitty
|
||||||
abbr -a :tgf kitty @ launch --type=tab --cwd ~/.config/fish # Kitty
|
abbr -a :tgk kitty @ launch --type=tab --cwd ~/.config/kitty # Kitty
|
||||||
abbr -a :tgh kitty @ launch --type=tab --cwd ~
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :tgcz kitty @ launch --type=tab --cwd ~/.local/share/chezmoi # Kitty
|
# @desc New tab at ~/.config/nvim
|
||||||
abbr -a :tgcm kitty @ launch --type=tab --cwd ~/.config/chezmoi # Kitty
|
abbr -a :tgn kitty @ launch --type=tab --cwd ~/.config/nvim # Kitty
|
||||||
abbr -a :tgp kitty @ launch --type=tab --cwd ~/projects # Kitty
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :tgr kitty @ launch --type=tab -- sudo -i
|
# @desc New tab at ~/.config/fish
|
||||||
end
|
abbr -a :tgf kitty @ launch --type=tab --cwd ~/.config/fish # Kitty
|
||||||
if test "$TERM_PROGRAM" = WezTerm
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :tgk wezterm cli spawn --cwd ~/.config/kitty # WezTerm
|
# @desc New tab at ~
|
||||||
abbr -a :tgn wezterm cli spawn --cwd ~/.config/nvim # WezTerm
|
abbr -a :tgh kitty @ launch --type=tab --cwd ~
|
||||||
abbr -a :tgf wezterm cli spawn --cwd ~/.config/fish # WezTerm
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :tgh wezterm cli spawn --cwd ~ # WezTerm
|
# @desc New tab at ~/.local/share/chezmoi
|
||||||
abbr -a :tgcz wezterm cli spawn --cwd ~/.local/share/chezmoi # WezTerm
|
abbr -a :tgcz kitty @ launch --type=tab --cwd ~/.local/share/chezmoi # Kitty
|
||||||
abbr -a :tgcm wezterm cli spawn --cwd ~/.config/chezmoi # WezTerm
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :tgp wezterm cli spawn --cwd ~/projects # WezTerm
|
# @desc New tab at ~/.config/chezmoi
|
||||||
abbr -a :tgr wezterm cli spawn -- sudo -i # WezTerm
|
abbr -a :tgcm kitty @ launch --type=tab --cwd ~/.config/chezmoi # Kitty
|
||||||
end
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New tab at ~/projects
|
||||||
|
abbr -a :tgp kitty @ launch --type=tab --cwd ~/projects # Kitty
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New tab at / (root)
|
||||||
|
abbr -a :tgr kitty @ launch --type=tab -- sudo -i
|
||||||
|
end
|
||||||
|
if test "$TERM_PROGRAM" = WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New tab at ~/.config/kitty
|
||||||
|
abbr -a :tgk wezterm cli spawn --cwd ~/.config/kitty # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New tab at ~/.config/nvim
|
||||||
|
abbr -a :tgn wezterm cli spawn --cwd ~/.config/nvim # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New tab at ~/.config/fish
|
||||||
|
abbr -a :tgf wezterm cli spawn --cwd ~/.config/fish # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New tab at ~
|
||||||
|
abbr -a :tgh wezterm cli spawn --cwd ~ # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New tab at ~/.local/share/chezmoi
|
||||||
|
abbr -a :tgcz wezterm cli spawn --cwd ~/.local/share/chezmoi # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New tab at ~/.config/chezmoi
|
||||||
|
abbr -a :tgcm wezterm cli spawn --cwd ~/.config/chezmoi # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New tab at ~/projects
|
||||||
|
abbr -a :tgp wezterm cli spawn --cwd ~/projects # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New tab at / (root)
|
||||||
|
abbr -a :tgr wezterm cli spawn -- sudo -i # WezTerm
|
||||||
|
end
|
||||||
|
|
||||||
# Specialty Window Shortcuts (New OS Window in specific dir)
|
# Specialty Window Shortcuts (New OS Window in specific dir)
|
||||||
if test "$TERM" = xterm-kitty
|
if test "$TERM" = xterm-kitty
|
||||||
abbr -a :wgk kitty @ launch --type=os-window --cwd ~/.config/kitty # Kitty
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :wgn kitty @ launch --type=os-window --cwd ~/.config/nvim # Kitty
|
# @desc New OS window at ~/.config/kitty
|
||||||
abbr -a :wgf kitty @ launch --type=os-window --cwd ~/.config/fish # Kitty
|
abbr -a :wgk kitty @ launch --type=os-window --cwd ~/.config/kitty # Kitty
|
||||||
abbr -a :wgh kitty @ launch --type=os-window --cwd ~
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :wgzd kitty @ launch --type=os-window --cwd ~/.local/share/chezmoi # Kitty
|
# @desc New OS window at ~/.config/nvim
|
||||||
abbr -a :wgcz kitty @ launch --type=os-window --cwd ~/.config/chezmoi # Kitty
|
abbr -a :wgn kitty @ launch --type=os-window --cwd ~/.config/nvim # Kitty
|
||||||
abbr -a :wgp kitty @ launch --type=os-window --cwd ~/projects # Kitty
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :wgr kitty @ launch --type=os-window -- sudo -i # Kitty
|
# @desc New OS window at ~/.config/fish
|
||||||
end
|
abbr -a :wgf kitty @ launch --type=os-window --cwd ~/.config/fish # Kitty
|
||||||
if test "$TERM_PROGRAM" = WezTerm
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :wgk wezterm cli spawn --new-window --cwd ~/.config/kitty # WezTerm
|
# @desc New OS window at ~
|
||||||
abbr -a :wgn wezterm cli spawn --new-window --cwd ~/.config/nvim # WezTerm
|
abbr -a :wgh kitty @ launch --type=os-window --cwd ~
|
||||||
abbr -a :wgf wezterm cli spawn --new-window --cwd ~/.config/fish # WezTerm
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :wgh wezterm cli spawn --new-window --cwd ~ # WezTerm
|
# @desc New OS window at ~/.local/share/chezmoi
|
||||||
abbr -a :wgzd wezterm cli spawn --new-window --cwd ~/.local/share/chezmoi # WezTerm
|
abbr -a :wgzd kitty @ launch --type=os-window --cwd ~/.local/share/chezmoi # Kitty
|
||||||
abbr -a :wgcz wezterm cli spawn --new-window --cwd ~/.config/chezmoi # WezTerm
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :wgp wezterm cli spawn --new-window --cwd ~/projects # WezTerm
|
# @desc New OS window at ~/.config/chezmoi
|
||||||
abbr -a :wgr wezterm cli spawn --new-window -- sudo -i # WezTerm
|
abbr -a :wgcz kitty @ launch --type=os-window --cwd ~/.config/chezmoi # Kitty
|
||||||
end
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New OS window at ~/projects
|
||||||
|
abbr -a :wgp kitty @ launch --type=os-window --cwd ~/projects # Kitty
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New OS window at / (root)
|
||||||
|
abbr -a :wgr kitty @ launch --type=os-window -- sudo -i # Kitty
|
||||||
|
end
|
||||||
|
if test "$TERM_PROGRAM" = WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New OS window at ~/.config/kitty
|
||||||
|
abbr -a :wgk wezterm cli spawn --new-window --cwd ~/.config/kitty # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New OS window at ~/.config/nvim
|
||||||
|
abbr -a :wgn wezterm cli spawn --new-window --cwd ~/.config/nvim # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New OS window at ~/.config/fish
|
||||||
|
abbr -a :wgf wezterm cli spawn --new-window --cwd ~/.config/fish # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New OS window at ~
|
||||||
|
abbr -a :wgh wezterm cli spawn --new-window --cwd ~ # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New OS window at ~/.local/share/chezmoi
|
||||||
|
abbr -a :wgzd wezterm cli spawn --new-window --cwd ~/.local/share/chezmoi # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New OS window at ~/.config/chezmoi
|
||||||
|
abbr -a :wgcz wezterm cli spawn --new-window --cwd ~/.config/chezmoi # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New OS window at ~/projects
|
||||||
|
abbr -a :wgp wezterm cli spawn --new-window --cwd ~/projects # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc New OS window at / (root)
|
||||||
|
abbr -a :wgr wezterm cli spawn --new-window -- sudo -i # WezTerm
|
||||||
|
end
|
||||||
|
|
||||||
# Specialty Window Vertical Shortcuts (Split Bottom)
|
# Specialty Window Vertical Shortcuts (Split Bottom)
|
||||||
if test "$TERM" = xterm-kitty
|
if test "$TERM" = xterm-kitty
|
||||||
abbr -a :wvgk kitty @ launch --location=hsplit --cwd ~/.config/kitty # Kitty
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :wvgn kitty @ launch --location=hsplit --cwd ~/.config/nvim # Kitty
|
# @desc Split bottom at ~/.config/kitty
|
||||||
abbr -a :wvgf kitty @ launch --location=hsplit --cwd ~/.config/fish # Kitty
|
abbr -a :wvgk kitty @ launch --location=hsplit --cwd ~/.config/kitty # Kitty
|
||||||
abbr -a :wvgh kitty @ launch --location=hsplit --cwd ~ # Kitty
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :wvgcz kitty @ launch --location=hsplit --cwd ~/.local/share/chezmoi # Kitty
|
# @desc Split bottom at ~/.config/nvim
|
||||||
abbr -a :wvgcm kitty @ launch --location=hsplit --cwd ~/.config/chezmoi # Kitty
|
abbr -a :wvgn kitty @ launch --location=hsplit --cwd ~/.config/nvim # Kitty
|
||||||
abbr -a :wvgp kitty @ launch --location=hsplit --cwd ~/projects # Kitty
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :wvgr kitty @ launch --location=hsplit -- sudo -i # Kitty
|
# @desc Split bottom at ~/.config/fish
|
||||||
end
|
abbr -a :wvgf kitty @ launch --location=hsplit --cwd ~/.config/fish # Kitty
|
||||||
if test "$TERM_PROGRAM" = WezTerm
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :wvgk wezterm cli split-pane --bottom --cwd ~/.config/kitty # WezTerm
|
# @desc Split bottom at ~
|
||||||
abbr -a :wvgn wezterm cli split-pane --bottom --cwd ~/.config/nvim # WezTerm
|
abbr -a :wvgh kitty @ launch --location=hsplit --cwd ~ # Kitty
|
||||||
abbr -a :wvgf wezterm cli split-pane --bottom --cwd ~/.config/fish # WezTerm
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :wvgh wezterm cli split-pane --bottom --cwd ~ # WezTerm
|
# @desc Split bottom at ~/.local/share/chezmoi
|
||||||
abbr -a :wvgcz wezterm cli split-pane --bottom --cwd ~/.local/share/chezmoi # WezTerm
|
abbr -a :wvgcz kitty @ launch --location=hsplit --cwd ~/.local/share/chezmoi # Kitty
|
||||||
abbr -a :wvgcm wezterm cli split-pane --bottom --cwd ~/.config/chezmoi # WezTerm
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :wvgp wezterm cli split-pane --bottom --cwd ~/projects # WezTerm
|
# @desc Split bottom at ~/.config/chezmoi
|
||||||
abbr -a :wvgr wezterm cli split-pane --bottom -- sudo -i # WezTerm
|
abbr -a :wvgcm kitty @ launch --location=hsplit --cwd ~/.config/chezmoi # Kitty
|
||||||
end
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Split bottom at ~/projects
|
||||||
|
abbr -a :wvgp kitty @ launch --location=hsplit --cwd ~/projects # Kitty
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Split bottom at / (root)
|
||||||
|
abbr -a :wvgr kitty @ launch --location=hsplit -- sudo -i # Kitty
|
||||||
|
end
|
||||||
|
if test "$TERM_PROGRAM" = WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Split bottom at ~/.config/kitty
|
||||||
|
abbr -a :wvgk wezterm cli split-pane --bottom --cwd ~/.config/kitty # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Split bottom at ~/.config/nvim
|
||||||
|
abbr -a :wvgn wezterm cli split-pane --bottom --cwd ~/.config/nvim # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Split bottom at ~/.config/fish
|
||||||
|
abbr -a :wvgf wezterm cli split-pane --bottom --cwd ~/.config/fish # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Split bottom at ~
|
||||||
|
abbr -a :wvgh wezterm cli split-pane --bottom --cwd ~ # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Split bottom at ~/.local/share/chezmoi
|
||||||
|
abbr -a :wvgcz wezterm cli split-pane --bottom --cwd ~/.local/share/chezmoi # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Split bottom at ~/.config/chezmoi
|
||||||
|
abbr -a :wvgcm wezterm cli split-pane --bottom --cwd ~/.config/chezmoi # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Split bottom at ~/projects
|
||||||
|
abbr -a :wvgp wezterm cli split-pane --bottom --cwd ~/projects # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Split bottom at / (root)
|
||||||
|
abbr -a :wvgr wezterm cli split-pane --bottom -- sudo -i # WezTerm
|
||||||
|
end
|
||||||
|
|
||||||
# Specialty Window Horizontal Shortcuts (Split Right)
|
# Specialty Window Horizontal Shortcuts (Split Right)
|
||||||
if test "$TERM" = xterm-kitty
|
if test "$TERM" = xterm-kitty
|
||||||
abbr -a :whgk kitty @ launch --location=vsplit --cwd ~/.config/kitty # Kitty
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :whgn kitty @ launch --location=vsplit --cwd ~/.config/nvim # Kitty
|
# @desc Split right at ~/.config/kitty
|
||||||
abbr -a :whgf kitty @ launch --location=vsplit --cwd ~/.config/fish # Kitty
|
abbr -a :whgk kitty @ launch --location=vsplit --cwd ~/.config/kitty # Kitty
|
||||||
abbr -a :whgh kitty @ launch --location=vsplit --cwd ~ # Kitty
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :whgcz kitty @ launch --location=vsplit --cwd ~/.local/share/chezmoi # Kitty
|
# @desc Split right at ~/.config/nvim
|
||||||
abbr -a :whgcm kitty @ launch --location=vsplit --cwd ~/.config/chezmoi # Kitty
|
abbr -a :whgn kitty @ launch --location=vsplit --cwd ~/.config/nvim # Kitty
|
||||||
abbr -a :whgp kitty @ launch --location=vsplit --cwd ~/projects # Kitty
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :whgr kitty @ launch --location=vsplit --cwd current sudo -i # Kitty -> Specialty cd Shortcuts
|
# @desc Split right at ~/.config/fish
|
||||||
abbr -a :cdk 'cd ~/.config/kitty/ # Kitty Config'
|
abbr -a :whgf kitty @ launch --location=vsplit --cwd ~/.config/fish # Kitty
|
||||||
abbr -a :cdkn 'cd ~/.config/kitty;nvim'
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
end
|
# @desc Split right at ~
|
||||||
if test "$TERM_PROGRAM" = WezTerm
|
abbr -a :whgh kitty @ launch --location=vsplit --cwd ~ # Kitty
|
||||||
abbr -a :whgk wezterm cli split-pane --bottom --cwd ~/.config/kitty # WezTerm
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :whgn wezterm cli split-pane --bottom --cwd ~/.config/nvim # WezTerm
|
# @desc Split right at ~/.local/share/chezmoi
|
||||||
abbr -a :whgf wezterm cli split-pane --bottom --cwd ~/.config/fish # WezTerm
|
abbr -a :whgcz kitty @ launch --location=vsplit --cwd ~/.local/share/chezmoi # Kitty
|
||||||
abbr -a :whgh wezterm cli split-pane --bottom --cwd ~ # WezTerm
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :whgcz wezterm cli split-pane --bottom --cwd ~/.local/share/chezmoi # WezTerm
|
# @desc Split right at ~/.config/chezmoi
|
||||||
abbr -a :whgcm wezterm cli split-pane --bottom --cwd ~/.config/chezmoi # WezTerm
|
abbr -a :whgcm kitty @ launch --location=vsplit --cwd ~/.config/chezmoi # Kitty
|
||||||
abbr -a :whgp wezterm cli split-pane --bottom --cwd ~/projects # WezTerm
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :whgr wezterm cli split-pane --bottom -- sudo -i # WezTerm
|
# @desc Split right at ~/projects
|
||||||
end
|
abbr -a :whgp kitty @ launch --location=vsplit --cwd ~/projects # Kitty
|
||||||
abbr -a :cdn cd '~/.config/nvim/ # Neovim Config'
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :cdnn 'cd ~/.config/nvim;nvim'
|
# @desc Split right at / (root)
|
||||||
abbr -a :cdf 'cd ~/.config/fish/ # Fish Config'
|
abbr -a :whgr kitty @ launch --location=vsplit --cwd current sudo -i # Kitty -> Specialty cd Shortcuts
|
||||||
abbr -a :cdfn 'cd ~/.config/fish;nvim'
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :cdh 'cd ~ # Home Directory'
|
# @desc cd ~/.config/kitty
|
||||||
abbr -a :cdhn 'cd ~;nvim'
|
abbr -a :cdk 'cd ~/.config/kitty/ # Kitty Config'
|
||||||
abbr -a :cdcz cd '~/.local/share/chezmoi/ # Chezmoi Source'
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :cdczn 'cd ~/.local/share/chezmoi;nvim'
|
# @desc cd ~/.config/kitty; nvim
|
||||||
abbr -a :cdcm 'cd ~/.config/chezmoi/ # Chezmoi Config'
|
abbr -a :cdkn 'cd ~/.config/kitty;nvim'
|
||||||
abbr -a :cdcmn 'cd ~/.config/chezmoi;nvim'
|
end
|
||||||
abbr -a :cdp --regex ':cdp' --set-cursor 'cd ~/projects/%'
|
if test "$TERM_PROGRAM" = WezTerm
|
||||||
# abbr -a cdp_slash --position anywhere --regex ':cdp/' --set-cursor 'cd ~/projects/%'
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
abbr -a :cdpn 'cd ~/projects;nvim'
|
# @desc Split right at ~/.config/kitty
|
||||||
abbr -a :cdw 'cd ~/.config/wezterm/ # WezTerm Config'
|
abbr -a :whgk wezterm cli split-pane --bottom --cwd ~/.config/kitty # WezTerm
|
||||||
abbr -a :cdwn 'cd ~/.config/wezterm;nvim'
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
if test "$TERM" = xterm-kitty
|
# @desc Split right at ~/.config/nvim
|
||||||
abbr -a editt kitty @ launch --type tab nvim
|
abbr -a :whgn wezterm cli split-pane --bottom --cwd ~/.config/nvim # WezTerm
|
||||||
end
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
# Spawn window
|
# @desc Split right at ~/.config/fish
|
||||||
if test "$TERM" = xterm-kitty
|
abbr -a :whgf wezterm cli split-pane --bottom --cwd ~/.config/fish # WezTerm
|
||||||
abbr -a :sw spwin
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Split right at ~
|
||||||
|
abbr -a :whgh wezterm cli split-pane --bottom --cwd ~ # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Split right at ~/.local/share/chezmoi
|
||||||
|
abbr -a :whgcz wezterm cli split-pane --bottom --cwd ~/.local/share/chezmoi # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Split right at ~/.config/chezmoi
|
||||||
|
abbr -a :whgcm wezterm cli split-pane --bottom --cwd ~/.config/chezmoi # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Split right at ~/projects
|
||||||
|
abbr -a :whgp wezterm cli split-pane --bottom --cwd ~/projects # WezTerm
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Split right at / (root)
|
||||||
|
abbr -a :whgr wezterm cli split-pane --bottom -- sudo -i # WezTerm
|
||||||
|
end
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc cd ~/.config/nvim
|
||||||
|
abbr -a :cdn cd '~/.config/nvim/ # Neovim Config'
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc cd ~/.config/nvim; nvim
|
||||||
|
abbr -a :cdnn 'cd ~/.config/nvim;nvim'
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc cd ~/.config/fish
|
||||||
|
abbr -a :cdf 'cd ~/.config/fish/ # Fish Config'
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc cd ~/.config/fish; nvim
|
||||||
|
abbr -a :cdfn 'cd ~/.config/fish;nvim'
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc cd ~
|
||||||
|
abbr -a :cdh 'cd ~ # Home Directory'
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc cd ~; nvim
|
||||||
|
abbr -a :cdhn 'cd ~;nvim'
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc cd ~/.local/share/chezmoi
|
||||||
|
abbr -a :cdcz cd '~/.local/share/chezmoi/ # Chezmoi Source'
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc cd ~/.local/share/chezmoi; nvim
|
||||||
|
abbr -a :cdczn 'cd ~/.local/share/chezmoi;nvim'
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc cd ~/.config/chezmoi
|
||||||
|
abbr -a :cdcm 'cd ~/.config/chezmoi/ # Chezmoi Config'
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc cd ~/.config/chezmoi; nvim
|
||||||
|
abbr -a :cdcmn 'cd ~/.config/chezmoi;nvim'
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc cd ~/projects/...
|
||||||
|
abbr -a :cdp --regex ':cdp' --set-cursor 'cd ~/projects/%'
|
||||||
|
# abbr -a cdp_slash --position anywhere --regex ':cdp/' --set-cursor 'cd ~/projects/%'
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc cd ~/projects; nvim
|
||||||
|
abbr -a :cdpn 'cd ~/projects;nvim'
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc cd ~/.config/wezterm
|
||||||
|
abbr -a :cdw 'cd ~/.config/wezterm/ # WezTerm Config'
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc cd ~/.config/wezterm; nvim
|
||||||
|
abbr -a :cdwn 'cd ~/.config/wezterm;nvim'
|
||||||
|
if test "$TERM" = xterm-kitty
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc Open new tab with nvim (terminal-aware)
|
||||||
|
abbr -a editt kitty @ launch --type tab nvim
|
||||||
|
end
|
||||||
|
# Spawn window
|
||||||
|
if test "$TERM" = xterm-kitty
|
||||||
|
# @category Terminal Windows, Tabs, and Panes
|
||||||
|
# @desc spwin (spawn new OS window)
|
||||||
|
abbr -a :sw spwin
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
### Docker ###
|
### Docker ###
|
||||||
|
# @category Docker
|
||||||
|
# @desc docker context use default
|
||||||
abbr -a dcl 'docker context use default # Local Host'
|
abbr -a dcl 'docker context use default # Local Host'
|
||||||
|
# @category Docker
|
||||||
|
# @desc ld (lazydocker)
|
||||||
abbr -a lzd ld
|
abbr -a lzd ld
|
||||||
|
# @category Docker
|
||||||
|
# @desc docker context ls
|
||||||
abbr -a dcls 'docker context ls'
|
abbr -a dcls 'docker context ls'
|
||||||
|
|
||||||
### Beads ###
|
### Beads ###
|
||||||
|
# @category Miscellaneous
|
||||||
|
# @desc bd list
|
||||||
abbr -a bl 'bd list'
|
abbr -a bl 'bd list'
|
||||||
|
# @category Miscellaneous
|
||||||
|
# @desc bd sync
|
||||||
abbr -a bs 'bd sync'
|
abbr -a bs 'bd sync'
|
||||||
|
# @category Miscellaneous
|
||||||
|
# @desc bd create --title
|
||||||
abbr -a bC 'bd create --title'
|
abbr -a bC 'bd create --title'
|
||||||
|
# @category Miscellaneous
|
||||||
|
# @desc bd show
|
||||||
abbr -a bsh 'bd show'
|
abbr -a bsh 'bd show'
|
||||||
|
# @category Miscellaneous
|
||||||
|
# @desc lazybeads
|
||||||
abbr -a lb lazybeads
|
abbr -a lb lazybeads
|
||||||
|
|
||||||
### Systemctl ###
|
### Systemctl ###
|
||||||
|
# @category Systemctl
|
||||||
|
# @desc systemctl
|
||||||
abbr -a sc systemctl
|
abbr -a sc systemctl
|
||||||
|
# @category Systemctl
|
||||||
|
# @desc sudo systemctl
|
||||||
abbr -a ssc 'sudo systemctl'
|
abbr -a ssc 'sudo systemctl'
|
||||||
|
# @category Systemctl
|
||||||
|
# @desc systemctl --user
|
||||||
abbr -a scu 'systemctl --user'
|
abbr -a scu 'systemctl --user'
|
||||||
|
# @category Systemctl
|
||||||
|
# @desc systemctl status
|
||||||
abbr -a st 'systemctl status'
|
abbr -a st 'systemctl status'
|
||||||
|
# @category Systemctl
|
||||||
|
# @desc systemctl start
|
||||||
abbr -a scs 'systemctl start'
|
abbr -a scs 'systemctl start'
|
||||||
|
# @category Systemctl
|
||||||
|
# @desc systemctl restart
|
||||||
abbr -a scr 'systemctl restart'
|
abbr -a scr 'systemctl restart'
|
||||||
|
# @category Systemctl
|
||||||
|
# @desc sudo systemctl status
|
||||||
abbr -a ssct 'sudo systemctl status'
|
abbr -a ssct 'sudo systemctl status'
|
||||||
|
# @category Systemctl
|
||||||
|
# @desc sudo systemctl start
|
||||||
abbr -a sscs 'sudo systemctl start'
|
abbr -a sscs 'sudo systemctl start'
|
||||||
|
# @category Systemctl
|
||||||
|
# @desc sudo systemctl restart
|
||||||
abbr -a sscr 'sudo systemctl restart'
|
abbr -a sscr 'sudo systemctl restart'
|
||||||
|
|
||||||
|
### Alternate command names ###
|
||||||
|
# Expand to the canonical function name so muscle-memory typos still work,
|
||||||
|
# while surfacing the real command instead of silently forwarding to it.
|
||||||
|
# @category Miscellaneous
|
||||||
|
# @desc repo-open
|
||||||
|
abbr -a open-repo repo-open
|
||||||
|
# @category Miscellaneous
|
||||||
|
# @desc open-url
|
||||||
|
abbr -a url-open open-url
|
||||||
|
|
||||||
### History Expansions and Substitutions ###
|
### History Expansions and Substitutions ###
|
||||||
abbr -a !^ --position anywhere --function expand_bang_caret
|
# Bash-style history expansion is opinionated (C3 overrides), gated atomically
|
||||||
abbr -a '!*' --position anywhere --function expand_bang_all
|
# with conf.d/tricks.fish, conf.d/puffer.fish, and functions/expand_*.fish.
|
||||||
abbr -a typo_sub --position anywhere --regex '\^([^^]+)\^([^^]*)' --function expand_typo_sub
|
if __fish_config_op_enabled __fish_config_op_overrides
|
||||||
abbr -a bang_string --position anywhere --regex '![\w.-]+' --function expand_bang_string
|
# @category History Expansion
|
||||||
abbr -a bang_search --position anywhere --regex '!\?[\w.-]+\??' --function expand_bang_search
|
# @name !^
|
||||||
abbr -a bang_minus_n --position anywhere --regex '!-(\d+)' --function expand_bang_minus_n
|
# @desc Expand to the first argument of the previous command
|
||||||
|
abbr -a !^ --position anywhere --function expand_bang_caret
|
||||||
|
# @category History Expansion
|
||||||
|
# @name !*
|
||||||
|
# @desc Expand to all arguments of the previous command
|
||||||
|
abbr -a '!*' --position anywhere --function expand_bang_all
|
||||||
|
# @category History Expansion
|
||||||
|
# @name ^old^new^
|
||||||
|
# @desc Interactive typo substitution (replace 'old' with 'new' in previous command)
|
||||||
|
abbr -a typo_sub --position anywhere --regex '\^([^^]+)\^([^^]*)' --function expand_typo_sub
|
||||||
|
# @category History Expansion
|
||||||
|
# @name !string
|
||||||
|
# @desc Expand to the most recent command starting with 'string'
|
||||||
|
abbr -a bang_string --position anywhere --regex '![\w.-]+' --function expand_bang_string
|
||||||
|
# @category History Expansion
|
||||||
|
# @name !?string?
|
||||||
|
# @desc Expand to the most recent command containing 'string'
|
||||||
|
abbr -a bang_search --position anywhere --regex '!\?[\w.-]+\??' --function expand_bang_search
|
||||||
|
# @category History Expansion
|
||||||
|
# @name !-n
|
||||||
|
# @desc Expand to the nth-previous command
|
||||||
|
abbr -a bang_minus_n --position anywhere --regex '!-(\d+)' --function expand_bang_minus_n
|
||||||
|
end
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
# ╭──────────────────────────────────────────────────────────╮
|
||||||
|
# │ Auto-Pull (C2 — Autoexec) │
|
||||||
|
# ╰──────────────────────────────────────────────────────────╯
|
||||||
|
#
|
||||||
|
# Background, fast-forward-only `git pull` for opted-in repositories. Fires
|
||||||
|
# when the working directory enters the fish-config repo (always covered as a
|
||||||
|
# baseline) or any repository registered via the `auto-pull` command. The
|
||||||
|
# actual sync is delegated to `_auto_pull_sync`, which only ever fast-forwards
|
||||||
|
# a clean repo — see that function for the full safety contract.
|
||||||
|
#
|
||||||
|
# Manage the registry with: auto-pull add / remove / list / status
|
||||||
|
|
||||||
|
# C2 guard: when auto-execution is disabled, do not register the handler.
|
||||||
|
__fish_config_op_enabled __fish_config_op_autoexec; or exit
|
||||||
|
|
||||||
|
# SYNOPSIS
|
||||||
|
# __auto_pull_on_pwd (event handler, --on-variable PWD)
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
# On every directory change, checks whether the new $PWD is inside a
|
||||||
|
# registered repository (or the fish-config baseline) and, if so, kicks a
|
||||||
|
# background fast-forward. A throttle global ensures it fires once per
|
||||||
|
# repository entry rather than on every sub-directory change.
|
||||||
|
function __auto_pull_on_pwd --on-variable PWD
|
||||||
|
set -q __fish_config_dir; or set -g __fish_config_dir $XDG_CONFIG_HOME/fish
|
||||||
|
set -q __fish_user_dots_path; or set -l __fish_user_dots_path "$XDG_CONFIG_HOME/.user-dots/fish"
|
||||||
|
set -l list "$__fish_user_dots_path/auto-pull.list"
|
||||||
|
|
||||||
|
# Candidate roots: the fish-config repo plus the user's registry.
|
||||||
|
set -l roots $__fish_config_dir
|
||||||
|
test -r "$list"; and set -a roots (command cat "$list" 2>/dev/null)
|
||||||
|
|
||||||
|
# Find the registered root containing $PWD (exact match or a sub-directory).
|
||||||
|
set -l hit
|
||||||
|
for r in $roots
|
||||||
|
test -n "$r"; or continue
|
||||||
|
if test "$PWD" = "$r"; or string match -q -- "$r/*" "$PWD"
|
||||||
|
set hit "$r"
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Outside every registered repo: clear the throttle so re-entry re-syncs.
|
||||||
|
if test -z "$hit"
|
||||||
|
set -e __auto_pull_last
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# Already synced for this repo entry — skip until we leave and return.
|
||||||
|
test "$hit" = "$__auto_pull_last"; and return
|
||||||
|
set -g __auto_pull_last "$hit"
|
||||||
|
|
||||||
|
# Background fast-forward. A --no-config child sources just the worker so
|
||||||
|
# it stays fast and free of shell side-effects; real `git`, no shadows.
|
||||||
|
set -l worker "$__fish_config_dir/functions/_auto_pull_sync.fish"
|
||||||
|
test -r "$worker"; or return
|
||||||
|
fish --no-config -c 'source $argv[1]; _auto_pull_sync $argv[2]' -- "$worker" "$hit" &
|
||||||
|
disown 2>/dev/null
|
||||||
|
end
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
status is-interactive || exit
|
status is-interactive || exit
|
||||||
|
|
||||||
|
# Local modification: opinionated guard (AGENTS.md Task #3). Bracket
|
||||||
|
# auto-pairing intercepts single-character input, classified as C3 overrides.
|
||||||
|
__fish_config_op_enabled __fish_config_op_overrides || exit
|
||||||
|
|
||||||
set --global autopair_left "(" "[" "{" '"' "'"
|
set --global autopair_left "(" "[" "{" '"' "'"
|
||||||
set --global autopair_right ")" "]" "}" '"' "'"
|
set --global autopair_right ")" "]" "}" '"' "'"
|
||||||
set --global autopair_pairs "()" "[]" "{}" '""' "''"
|
set --global autopair_pairs "()" "[]" "{}" '""' "''"
|
||||||
|
|||||||
@@ -0,0 +1,138 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
# Provides bash-style history expansion functions for abbreviations.
|
||||||
|
# These functions are gated by the C3 overrides switch.
|
||||||
|
|
||||||
|
# Execute expand_bang_all
|
||||||
|
function expand_bang_all --description 'Execute expand_bang_all'
|
||||||
|
# Opinionated guard (C3): no expansion when overrides are disabled.
|
||||||
|
__fish_config_op_enabled __fish_config_op_overrides; or return 1
|
||||||
|
|
||||||
|
set -l token $argv[1]
|
||||||
|
if test -z "$token"; set token (commandline -t); end
|
||||||
|
|
||||||
|
set -l tokens (string split -n " " -- $history[1])
|
||||||
|
if test (count $tokens) -gt 1
|
||||||
|
echo -- (string join " " -- $tokens[2..-1])
|
||||||
|
else
|
||||||
|
echo -- $token
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Execute expand_bang_caret
|
||||||
|
function expand_bang_caret --description 'Execute expand_bang_caret'
|
||||||
|
# Opinionated guard (C3): no expansion when overrides are disabled.
|
||||||
|
__fish_config_op_enabled __fish_config_op_overrides; or return 1
|
||||||
|
|
||||||
|
# Split the last history item into a list
|
||||||
|
set -l tokens (string split -n ' ' -- $history[1])
|
||||||
|
# tokens[1] is the command, tokens[2] is the first argument
|
||||||
|
if set -q tokens[2]
|
||||||
|
echo -- $tokens[2]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Execute expand_bang_minus_n
|
||||||
|
function expand_bang_minus_n --description 'Execute expand_bang_minus_n'
|
||||||
|
# Opinionated guard (C3): no expansion when overrides are disabled.
|
||||||
|
__fish_config_op_enabled __fish_config_op_overrides; or return 1
|
||||||
|
|
||||||
|
set -l token $argv[1]
|
||||||
|
if test -z "$token"; set token (commandline -t); end
|
||||||
|
|
||||||
|
# Extract the number from the regex match
|
||||||
|
if string match -qr '!-(\d+)' -- "$token"
|
||||||
|
set -l n (string match -r '!-(\d+)' -- "$token")[2]
|
||||||
|
|
||||||
|
if test (count $history) -ge $n
|
||||||
|
echo -- $history[$n]
|
||||||
|
else
|
||||||
|
echo -- $token
|
||||||
|
end
|
||||||
|
else
|
||||||
|
echo -- $token
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Execute expand_bang_search
|
||||||
|
function expand_bang_search --description 'Execute expand_bang_search'
|
||||||
|
# Opinionated guard (C3): no expansion when overrides are disabled.
|
||||||
|
__fish_config_op_enabled __fish_config_op_overrides; or return 1
|
||||||
|
|
||||||
|
set -l token $argv[1]
|
||||||
|
if test -z "$token"
|
||||||
|
set token (commandline -t)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Extract query: looks for text after !? and before an optional ?
|
||||||
|
set -l query (string match -r '!\?([^?]+)' -- $token)[2]
|
||||||
|
|
||||||
|
if test -n "$query"
|
||||||
|
# Search history for a match anywhere in the command
|
||||||
|
set -l match (builtin history search --contains --max=1 -- $query)
|
||||||
|
|
||||||
|
if test -n "$match"
|
||||||
|
echo -- $match
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
echo -- $token
|
||||||
|
end
|
||||||
|
|
||||||
|
# Execute expand_bang_string
|
||||||
|
function expand_bang_string --description 'Execute expand_bang_string'
|
||||||
|
# Opinionated guard (C3): no expansion when overrides are disabled.
|
||||||
|
__fish_config_op_enabled __fish_config_op_overrides; or return 1
|
||||||
|
|
||||||
|
# Fish 4.x passes the matched token as argv[1]
|
||||||
|
set -l token $argv[1]
|
||||||
|
if test -z "$token"
|
||||||
|
set token (commandline -t)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Remove the '!' to get the search query
|
||||||
|
set -l query (string sub -s 2 -- $token)
|
||||||
|
|
||||||
|
if test -n "$query"
|
||||||
|
# Search history for a prefix match
|
||||||
|
set -l match (builtin history search --prefix --max=1 -- $query)
|
||||||
|
|
||||||
|
if test -n "$match"
|
||||||
|
echo -- $match
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# If no match or empty query, return the token so it doesn't vanish
|
||||||
|
echo -- $token
|
||||||
|
end
|
||||||
|
|
||||||
|
# Execute expand_typo_sub
|
||||||
|
function expand_typo_sub --description 'Execute expand_typo_sub'
|
||||||
|
# Opinionated guard (C3): no expansion when overrides are disabled.
|
||||||
|
__fish_config_op_enabled __fish_config_op_overrides; or return 1
|
||||||
|
|
||||||
|
# In newer Fish, the matched token is often passed as $argv[1]
|
||||||
|
# if the abbr is set up correctly. We'll fallback to commandline just in case.
|
||||||
|
set -l last_cmd $history[1]
|
||||||
|
set -l current_token $argv[1]
|
||||||
|
if test -z "$current_token"
|
||||||
|
set current_token (commandline -t)
|
||||||
|
end
|
||||||
|
|
||||||
|
if string match -qr '\^([^^]+)\^([^^]*)' -- "$current_token"
|
||||||
|
set -l captured (string match -r '\^([^^]+)\^([^^]*)' -- "$current_token")
|
||||||
|
set -l old $captured[2]
|
||||||
|
set -l new $captured[3]
|
||||||
|
|
||||||
|
if test -n "$old"
|
||||||
|
# Using -- to ensure strings starting with '-' aren't treated as flags
|
||||||
|
echo -- (string replace -a -- "$old" "$new" "$last_cmd")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
# Return the token itself so it doesn't vanish
|
||||||
|
echo -- "$current_token"
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,344 @@
|
|||||||
|
# MIT License
|
||||||
|
|
||||||
|
# Copyright (c) 2016 Francisco Lourenço & Daniel Wehner
|
||||||
|
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
|
||||||
|
if not status is-interactive
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
|
||||||
|
# Local modification: opinionated guard (AGENTS.md Task #3). Desktop
|
||||||
|
# notifications assume a graphical session, classified as C4 integrations.
|
||||||
|
__fish_config_op_enabled __fish_config_op_integrations; or exit
|
||||||
|
|
||||||
|
set -g __done_version 1.19.1
|
||||||
|
|
||||||
|
function __done_run_powershell_script
|
||||||
|
set -l powershell_exe (command --search "powershell.exe")
|
||||||
|
|
||||||
|
if test $status -ne 0
|
||||||
|
and command --search wslvar
|
||||||
|
|
||||||
|
set -l powershell_exe (wslpath (wslvar windir)/System32/WindowsPowerShell/v1.0/powershell.exe)
|
||||||
|
end
|
||||||
|
|
||||||
|
if string length --quiet "$powershell_exe"
|
||||||
|
and test -x "$powershell_exe"
|
||||||
|
|
||||||
|
set cmd (string escape $argv)
|
||||||
|
|
||||||
|
eval "$powershell_exe -Command $cmd"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function __done_windows_notification -a title -a message
|
||||||
|
if test "$__done_notify_sound" -eq 1
|
||||||
|
set soundopt "<audio silent=\"false\" src=\"ms-winsoundevent:Notification.Default\" />"
|
||||||
|
else
|
||||||
|
set soundopt "<audio silent=\"true\" />"
|
||||||
|
end
|
||||||
|
|
||||||
|
__done_run_powershell_script "
|
||||||
|
[Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] | Out-Null
|
||||||
|
[Windows.UI.Notifications.ToastNotification, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null
|
||||||
|
|
||||||
|
\$toast_xml_source = @\"
|
||||||
|
<toast>
|
||||||
|
$soundopt
|
||||||
|
<visual>
|
||||||
|
<binding template=\"ToastText02\">
|
||||||
|
<text id=\"1\">$title</text>
|
||||||
|
<text id=\"2\">$message</text>
|
||||||
|
</binding>
|
||||||
|
</visual>
|
||||||
|
</toast>
|
||||||
|
\"@
|
||||||
|
|
||||||
|
\$toast_xml = New-Object Windows.Data.Xml.Dom.XmlDocument
|
||||||
|
\$toast_xml.loadXml(\$toast_xml_source)
|
||||||
|
|
||||||
|
\$toast = New-Object Windows.UI.Notifications.ToastNotification \$toast_xml
|
||||||
|
|
||||||
|
[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier(\"fish\").Show(\$toast)
|
||||||
|
"
|
||||||
|
end
|
||||||
|
|
||||||
|
function __done_get_focused_window_id
|
||||||
|
if type -q lsappinfo
|
||||||
|
lsappinfo info -only bundleID (lsappinfo front | string replace 'ASN:0x0-' '0x') | cut -d '"' -f4
|
||||||
|
else if test -n "$SWAYSOCK"
|
||||||
|
and type -q jq
|
||||||
|
swaymsg --type get_tree | jq '.. | objects | select(.focused == true) | .id'
|
||||||
|
else if test -n "$HYPRLAND_INSTANCE_SIGNATURE"
|
||||||
|
hyprctl activewindow | awk '/^\tpid: / {print $2}'
|
||||||
|
else if begin
|
||||||
|
test "$XDG_SESSION_DESKTOP" = gnome; and type -q gdbus
|
||||||
|
end
|
||||||
|
gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell --method org.gnome.Shell.Eval 'global.display.focus_window.get_id()'
|
||||||
|
else if type -q xprop
|
||||||
|
and test -n "$DISPLAY"
|
||||||
|
# Test that the X server at $DISPLAY is running
|
||||||
|
and xprop -grammar >/dev/null 2>&1
|
||||||
|
xprop -root 32x '\t$0' _NET_ACTIVE_WINDOW | cut -f 2
|
||||||
|
else if uname -a | string match --quiet --ignore-case --regex microsoft
|
||||||
|
__done_run_powershell_script '
|
||||||
|
Add-Type @"
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
public class WindowsCompat {
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern IntPtr GetForegroundWindow();
|
||||||
|
}
|
||||||
|
"@
|
||||||
|
[WindowsCompat]::GetForegroundWindow()
|
||||||
|
'
|
||||||
|
else if set -q __done_allow_nongraphical
|
||||||
|
echo 12345 # dummy value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function __done_is_tmux_window_active
|
||||||
|
set -q fish_pid; or set -l fish_pid %self
|
||||||
|
|
||||||
|
# find the outermost process within tmux
|
||||||
|
# ppid != "tmux" -> pid = ppid
|
||||||
|
# ppid == "tmux" -> break
|
||||||
|
set tmux_fish_pid $fish_pid
|
||||||
|
while set tmux_fish_ppid (ps -o ppid= -p $tmux_fish_pid | string trim)
|
||||||
|
# remove leading hyphen so that basename does not treat it as an argument (e.g. -fish), and return only
|
||||||
|
# the actual command and not its arguments so that basename finds the correct command name.
|
||||||
|
# (e.g. '/usr/bin/tmux' from command '/usr/bin/tmux new-session -c /some/start/dir')
|
||||||
|
and ! string match -q "tmux*" (basename (ps -o command= -p $tmux_fish_ppid | string replace -r '^-' '' | string split ' ')[1])
|
||||||
|
set tmux_fish_pid $tmux_fish_ppid
|
||||||
|
end
|
||||||
|
|
||||||
|
# tmux session attached and window is active -> no notification
|
||||||
|
# all other combinations -> send notification
|
||||||
|
tmux list-panes -a -F "#{session_attached} #{window_active} #{pane_pid}" | string match -q "1 1 $tmux_fish_pid"
|
||||||
|
end
|
||||||
|
|
||||||
|
function __done_is_screen_window_active
|
||||||
|
string match --quiet --regex "$STY\s+\(Attached" (screen -ls)
|
||||||
|
end
|
||||||
|
|
||||||
|
function __done_is_process_window_focused
|
||||||
|
# Return false if the window is not focused
|
||||||
|
|
||||||
|
if set -q __done_allow_nongraphical
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if set -q __done_kitty_remote_control
|
||||||
|
kitty @ --password="$__done_kitty_remote_control_password" ls | jq -e ".[].tabs[] | select(any(.windows[]; .is_self)) | .is_focused" >/dev/null
|
||||||
|
return $status
|
||||||
|
end
|
||||||
|
|
||||||
|
set __done_focused_window_id (__done_get_focused_window_id)
|
||||||
|
if test "$__done_sway_ignore_visible" -eq 1
|
||||||
|
and test -n "$SWAYSOCK"
|
||||||
|
string match --quiet --regex "^true" (swaymsg -t get_tree | jq ".. | objects | select(.id == "$__done_initial_window_id") | .visible")
|
||||||
|
return $status
|
||||||
|
else if test -n "$HYPRLAND_INSTANCE_SIGNATURE"
|
||||||
|
set window_pid (hyprctl activewindow | awk '/^\tpid: / {print $2}')
|
||||||
|
if test -n "$window_pid"
|
||||||
|
and test $__done_initial_window_id -eq $window_pid
|
||||||
|
return $status
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
else if test "$__done_initial_window_id" != "$__done_focused_window_id"
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
# If inside a tmux session, check if the tmux window is focused
|
||||||
|
if type -q tmux
|
||||||
|
and test -n "$TMUX"
|
||||||
|
__done_is_tmux_window_active
|
||||||
|
return $status
|
||||||
|
end
|
||||||
|
|
||||||
|
# If inside a screen session, check if the screen window is focused
|
||||||
|
if type -q screen
|
||||||
|
and test -n "$STY"
|
||||||
|
__done_is_screen_window_active
|
||||||
|
return $status
|
||||||
|
end
|
||||||
|
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function __done_humanize_duration -a milliseconds
|
||||||
|
set -l seconds (math --scale=0 "$milliseconds/1000" % 60)
|
||||||
|
set -l minutes (math --scale=0 "$milliseconds/60000" % 60)
|
||||||
|
set -l hours (math --scale=0 "$milliseconds/3600000")
|
||||||
|
|
||||||
|
if test $hours -gt 0
|
||||||
|
printf '%s' $hours'h '
|
||||||
|
end
|
||||||
|
if test $minutes -gt 0
|
||||||
|
printf '%s' $minutes'm '
|
||||||
|
end
|
||||||
|
if test $seconds -gt 0
|
||||||
|
printf '%s' $seconds's'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# verify that the system has graphical capabilities before initializing
|
||||||
|
if test -z "$SSH_CLIENT" # not over ssh
|
||||||
|
and count (__done_get_focused_window_id) >/dev/null # is able to get window id
|
||||||
|
set __done_enabled
|
||||||
|
end
|
||||||
|
|
||||||
|
if set -q __done_allow_nongraphical
|
||||||
|
and set -q __done_notification_command
|
||||||
|
set __done_enabled
|
||||||
|
end
|
||||||
|
|
||||||
|
if set -q __done_enabled
|
||||||
|
set -g __done_initial_window_id ''
|
||||||
|
set -q __done_min_cmd_duration; or set -g __done_min_cmd_duration 5000
|
||||||
|
set -q __done_exclude; or set -g __done_exclude '^git (?!push|pull|fetch)'
|
||||||
|
set -q __done_notify_sound; or set -g __done_notify_sound 0
|
||||||
|
set -q __done_sway_ignore_visible; or set -g __done_sway_ignore_visible 0
|
||||||
|
set -q __done_tmux_pane_format; or set -g __done_tmux_pane_format '[#{window_index}]'
|
||||||
|
set -q __done_notification_duration; or set -g __done_notification_duration 3000
|
||||||
|
|
||||||
|
function __done_started --on-event fish_preexec
|
||||||
|
set __done_initial_window_id (__done_get_focused_window_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
function __done_ended --on-event fish_postexec
|
||||||
|
set -l exit_status $status
|
||||||
|
|
||||||
|
# backwards compatibility for fish < v3.0
|
||||||
|
set -q cmd_duration; or set -l cmd_duration $CMD_DURATION
|
||||||
|
|
||||||
|
if test $cmd_duration
|
||||||
|
and test $cmd_duration -gt $__done_min_cmd_duration # longer than notify_duration
|
||||||
|
and not __done_is_process_window_focused # process pane or window not focused
|
||||||
|
|
||||||
|
# don't notify if command matches exclude list
|
||||||
|
for pattern in $__done_exclude
|
||||||
|
if string match -qr $pattern $argv[1]
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Store duration of last command
|
||||||
|
set -l humanized_duration (__done_humanize_duration "$cmd_duration")
|
||||||
|
|
||||||
|
set -l title "Done in $humanized_duration"
|
||||||
|
set -l wd (string replace --regex "^$HOME" "~" (pwd))
|
||||||
|
set -l message "$wd/ $argv[1]"
|
||||||
|
set -l sender $__done_initial_window_id
|
||||||
|
|
||||||
|
if test $exit_status -ne 0
|
||||||
|
set title "Failed ($exit_status) after $humanized_duration"
|
||||||
|
end
|
||||||
|
|
||||||
|
if test -n "$TMUX_PANE"
|
||||||
|
set message (tmux lsw -F"$__done_tmux_pane_format" -f '#{==:#{pane_id},'$TMUX_PANE'}')" $message"
|
||||||
|
end
|
||||||
|
|
||||||
|
if set -q __done_notification_command
|
||||||
|
eval $__done_notification_command
|
||||||
|
if test "$__done_notify_sound" -eq 1
|
||||||
|
echo -e "\a" # bell sound
|
||||||
|
end
|
||||||
|
else if set -q KITTY_WINDOW_ID
|
||||||
|
printf "\x1b]99;i=done:d=0;$title\x1b\\"
|
||||||
|
printf "\x1b]99;i=done:d=1:p=body;$message\x1b\\"
|
||||||
|
else if type -q terminal-notifier # https://github.com/julienXX/terminal-notifier
|
||||||
|
if test "$__done_notify_sound" -eq 1
|
||||||
|
# pipe message into terminal-notifier to avoid escaping issues (https://github.com/julienXX/terminal-notifier/issues/134). fixes #140
|
||||||
|
echo "$message" | terminal-notifier -title "$title" -sender "$__done_initial_window_id" -sound default
|
||||||
|
else
|
||||||
|
echo "$message" | terminal-notifier -title "$title" -sender "$__done_initial_window_id"
|
||||||
|
end
|
||||||
|
|
||||||
|
else if type -q osascript # AppleScript
|
||||||
|
# escape double quotes that might exist in the message and break osascript. fixes #133
|
||||||
|
set -l message (string replace --all '"' '\"' "$message")
|
||||||
|
set -l title (string replace --all '"' '\"' "$title")
|
||||||
|
|
||||||
|
osascript -e "display notification \"$message\" with title \"$title\""
|
||||||
|
if test "$__done_notify_sound" -eq 1
|
||||||
|
osascript -e "display notification \"$message\" with title \"$title\" sound name \"Glass\""
|
||||||
|
else
|
||||||
|
osascript -e "display notification \"$message\" with title \"$title\""
|
||||||
|
end
|
||||||
|
|
||||||
|
else if type -q notify-send # Linux notify-send
|
||||||
|
# set urgency to normal
|
||||||
|
set -l urgency normal
|
||||||
|
|
||||||
|
# use user-defined urgency if set
|
||||||
|
if set -q __done_notification_urgency_level
|
||||||
|
set urgency "$__done_notification_urgency_level"
|
||||||
|
end
|
||||||
|
# override user-defined urgency level if non-zero exitstatus
|
||||||
|
if test $exit_status -ne 0
|
||||||
|
set urgency critical
|
||||||
|
if set -q __done_notification_urgency_level_failure
|
||||||
|
set urgency "$__done_notification_urgency_level_failure"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
notify-send --hint=int:transient:1 --urgency=$urgency --icon=utilities-terminal --app-name=fish --expire-time=$__done_notification_duration "$title" "$message"
|
||||||
|
|
||||||
|
if test "$__done_notify_sound" -eq 1
|
||||||
|
echo -e "\a" # bell sound
|
||||||
|
end
|
||||||
|
|
||||||
|
else if type -q notify-desktop # Linux notify-desktop
|
||||||
|
set -l urgency
|
||||||
|
if test $exit_status -ne 0
|
||||||
|
set urgency "--urgency=critical"
|
||||||
|
end
|
||||||
|
notify-desktop $urgency --icon=utilities-terminal --app-name=fish "$title" "$message"
|
||||||
|
if test "$__done_notify_sound" -eq 1
|
||||||
|
echo -e "\a" # bell sound
|
||||||
|
end
|
||||||
|
|
||||||
|
else if uname -a | string match --quiet --ignore-case --regex microsoft
|
||||||
|
__done_windows_notification "$title" "$message"
|
||||||
|
|
||||||
|
else # anything else
|
||||||
|
echo -e "\a" # bell sound
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function __done_uninstall -e done_uninstall
|
||||||
|
# Erase all __done_* functions
|
||||||
|
functions -e __done_ended
|
||||||
|
functions -e __done_started
|
||||||
|
functions -e __done_get_focused_window_id
|
||||||
|
functions -e __done_is_tmux_window_active
|
||||||
|
functions -e __done_is_screen_window_active
|
||||||
|
functions -e __done_is_process_window_focused
|
||||||
|
functions -e __done_windows_notification
|
||||||
|
functions -e __done_run_powershell_script
|
||||||
|
functions -e __done_humanize_duration
|
||||||
|
|
||||||
|
# Erase __done variables
|
||||||
|
set -e __done_version
|
||||||
|
end
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
# ╭──────────────────────────────────────────────────────────╮
|
||||||
|
# │ First-Run Initialization │
|
||||||
|
# ╰──────────────────────────────────────────────────────────╯
|
||||||
|
#
|
||||||
|
# Runs exactly once on the first interactive fish session after install.
|
||||||
|
# To reset for testing, run: set -Ue __fish_config_first_run_complete
|
||||||
|
|
||||||
|
# Exit early in non-interactive shells (scripts, completions, subshells)
|
||||||
|
if not status is-interactive
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# Skip if this shell has already been initialized
|
||||||
|
if set -q __fish_config_first_run_complete
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# Set the flag immediately — before actions — so a mid-run crash doesn't
|
||||||
|
# leave the shell in a state that re-triggers everything next session.
|
||||||
|
set -U __fish_config_first_run_complete 1
|
||||||
|
|
||||||
|
# ──────────────────────────── Man page symlink ──────────────────────────
|
||||||
|
# Install fish-config.1 into the user man database once, like an install step.
|
||||||
|
# Unconditional: standard enough that no category gate is warranted.
|
||||||
|
set -l _man1 ~/.local/share/man/man1
|
||||||
|
set -l _src ~/.config/fish/docs/fish-config.1
|
||||||
|
if test -f $_src; and not test -L $_man1/fish-config.1
|
||||||
|
mkdir -p $_man1
|
||||||
|
ln -sf $_src $_man1/fish-config.1
|
||||||
|
end
|
||||||
|
|
||||||
|
# ──────────────────────────── Welcome message ───────────────────────────
|
||||||
|
# Printing a first-run welcome banner is opinionated (C6 greeting). The
|
||||||
|
# first-run state variable is already set unconditionally above, so
|
||||||
|
# disabling the greeting never re-triggers this file.
|
||||||
|
if __fish_config_op_enabled __fish_config_op_greeting
|
||||||
|
echo ""
|
||||||
|
echo " Welcome to your fish shell configuration!"
|
||||||
|
echo " Run 'help config' for offline documentation."
|
||||||
|
echo " Run 'fish-deps' to check and install dependencies."
|
||||||
|
echo ""
|
||||||
|
end
|
||||||
|
|
||||||
|
# ─────────────────────── Opinionated auto-exec guard ────────────────────
|
||||||
|
# Startup side-effects below (Fisher curl, fisher update, theme apply) are
|
||||||
|
# opinionated (C2 auto-execution). The first-run state variable is already
|
||||||
|
# set above either way, so disabling auto-exec never re-triggers this file.
|
||||||
|
if not __fish_config_op_enabled __fish_config_op_autoexec
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# ──────────────────────────── Bootstrap Fisher ──────────────────────────
|
||||||
|
if not type -q fisher
|
||||||
|
echo " [first-run] Installing Fisher plugin manager..."
|
||||||
|
if curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source
|
||||||
|
echo " [first-run] Fisher installed."
|
||||||
|
if not fisher update 2>/dev/null
|
||||||
|
echo " [first-run] Fisher update failed — run 'fisher update' manually." >&2
|
||||||
|
end
|
||||||
|
else
|
||||||
|
echo " [first-run] Fisher install failed — run 'fisher update' manually." >&2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# ───────────────────────────── Apply theme ──────────────────────────────
|
||||||
|
# Catppuccin Mocha theme ships with this config in themes/; it is always available.
|
||||||
|
if not fish_config theme choose "Catppuccin Mocha" 2>/dev/null
|
||||||
|
echo " [first-run] Could not apply Catppuccin Mocha theme — set manually with 'fish_config theme choose'." >&2
|
||||||
|
end
|
||||||
+2
-1
@@ -9,7 +9,8 @@ end
|
|||||||
# This variable is global so that it can be referenced by fzf_configure_bindings and in tests
|
# This variable is global so that it can be referenced by fzf_configure_bindings and in tests
|
||||||
set --global _fzf_search_vars_command '_fzf_search_variables (set --show | psub) (set --names | psub)'
|
set --global _fzf_search_vars_command '_fzf_search_variables (set --show | psub) (set --names | psub)'
|
||||||
|
|
||||||
# Install the default bindings, which are mnemonic and minimally conflict with fish's preset bindings
|
# Install the default bindings only if fzf is available
|
||||||
|
type -q fzf || exit
|
||||||
fzf_configure_bindings
|
fzf_configure_bindings
|
||||||
|
|
||||||
# Doesn't erase autoloaded _fzf_* functions because they are not easily accessible once key bindings are erased
|
# Doesn't erase autoloaded _fzf_* functions because they are not easily accessible once key bindings are erased
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# ╭──────────────────────────────────────────────────────────╮
|
||||||
|
# │ help config wrapper │
|
||||||
|
# ╰──────────────────────────────────────────────────────────╯
|
||||||
|
#
|
||||||
|
# SYNOPSIS
|
||||||
|
# help [topic] [sub-topic...]
|
||||||
|
# help config [section] [-w|--html] [-m|--man] [-h|--help]
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
# Wraps the built-in Fish help command. Intercepts the specific topic
|
||||||
|
# "config" and forwards any subsequent sub-topics/arguments straight to the
|
||||||
|
# custom 'config-help' utility. For all other topics, it forwards the
|
||||||
|
# arguments intact to the original, built-in system help utility.
|
||||||
|
#
|
||||||
|
# When the first argument is "config", the following flags are recognized
|
||||||
|
# and delegated to 'config-help':
|
||||||
|
# -w, --html Open the offline HTML docs in the default browser
|
||||||
|
# -m, --man Open the compiled man page via man -l
|
||||||
|
# -h, --help Print config-help usage reference
|
||||||
|
#
|
||||||
|
# Flags that appear WITHOUT a leading "config" argument — including
|
||||||
|
# -h/--help — are forwarded unchanged to the native Fish help command, so
|
||||||
|
# built-in behavior is never overridden for non-config topics.
|
||||||
|
#
|
||||||
|
# NOTES
|
||||||
|
# To prevent infinite recursion, the wrapper backs up the native help
|
||||||
|
# function as '__original_help' before shadowing it. This MUST happen from
|
||||||
|
# conf.d, not functions/help.fish: as of Fish 4.x the native help is
|
||||||
|
# embedded in the binary (embedded:functions/help.fish) with no on-disk
|
||||||
|
# file to source, and a functions/help.fish autoload shadow makes the name
|
||||||
|
# 'help' resolve to our own wrapper (or nothing, mid-autoload) — so the
|
||||||
|
# backup could never capture the real help. Sourced here at startup, before
|
||||||
|
# any shadow exists, `functions -c help` copies the embedded original.
|
||||||
|
#
|
||||||
|
# EXAMPLE
|
||||||
|
# help config keys # → config-help keys
|
||||||
|
# help config --html # opens the offline HTML docs in the browser
|
||||||
|
# help config keys --man # opens the compiled man page via man -l
|
||||||
|
# help string # forwards to native fish docs for 'string'
|
||||||
|
|
||||||
|
# --- Initialization & Backup ---
|
||||||
|
# Copy the native (embedded) help to __original_help before we shadow it.
|
||||||
|
if not functions -q __original_help
|
||||||
|
functions -c help __original_help
|
||||||
|
end
|
||||||
|
|
||||||
|
# --- Wrapper Definition ---
|
||||||
|
function help --wraps help --description "Custom wrapper to intercept 'help config'"
|
||||||
|
# Opinionated guard (C1): fall back to the native fish help when disabled.
|
||||||
|
if not __fish_config_op_enabled __fish_config_op_aliases
|
||||||
|
__original_help $argv
|
||||||
|
return $status
|
||||||
|
end
|
||||||
|
|
||||||
|
if test "$argv[1]" = config
|
||||||
|
# All arguments after 'config' — including flags (-w/--html, -m/--man,
|
||||||
|
# -h/--help) and section keywords — are forwarded to config-help.
|
||||||
|
# Flags are only intercepted here when 'config' is the first argument,
|
||||||
|
# so native fish help flags are never shadowed for other topics.
|
||||||
|
config-help $argv[2..]
|
||||||
|
else
|
||||||
|
__original_help $argv
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -36,14 +36,31 @@
|
|||||||
# If the current command text is empty, the previous command's first token will be used instead.
|
# If the current command text is empty, the previous command's first token will be used instead.
|
||||||
# ──────────────────────────────────────────────────────────────────────
|
# ──────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
# ────────────── Bind Quick Qalc Evaluation to Ctrl+Alt+= ──────────────
|
||||||
|
# Passes the current command line buffer to the Qalculate! CLI (qalc)
|
||||||
|
#
|
||||||
|
# Example: If you type `150 * 1.08` and press Ctrl+Alt+=,
|
||||||
|
# it will print the result (162) and clear the command line.
|
||||||
|
# This allows for rapid-fire math without leaving the current shell.
|
||||||
|
# ──────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
function fish_user_key_bindings
|
function fish_user_key_bindings
|
||||||
|
|
||||||
|
# Custom key chords are opinionated (C3 overrides); skip them entirely
|
||||||
|
# when overrides are disabled so stock bindings remain untouched.
|
||||||
|
__fish_config_op_enabled __fish_config_op_overrides; or return
|
||||||
|
|
||||||
# ───────────────────────────── Set Bindings ─────────────────────────────
|
# ───────────────────────────── Set Bindings ─────────────────────────────
|
||||||
#
|
#
|
||||||
# Set Emacs mode bindings:
|
# Set Emacs mode bindings:
|
||||||
bind ctrl-g __insert_previous_path_head
|
bind ctrl-g __insert_previous_path_head
|
||||||
bind ctrl-f __interactive_history_sub
|
bind ctrl-f __interactive_history_sub
|
||||||
bind ctrl-alt-u _replace_command_token
|
bind ctrl-alt-u _replace_command_token
|
||||||
|
type -q qalc && bind ctrl-alt-= _qalc_eval
|
||||||
|
bind ctrl-enter _smart_execute
|
||||||
|
bind @@ __fzf_inline_picker
|
||||||
|
bind ctrl-right nextd-or-forward-word
|
||||||
|
bind \e\[1\;5C nextd-or-forward-word
|
||||||
|
|
||||||
# Set bindings for all Vi modes:
|
# Set bindings for all Vi modes:
|
||||||
# 'default' is Vi-Command, 'insert' is Vi-Insert, 'visual' is Vi-Visual
|
# 'default' is Vi-Command, 'insert' is Vi-Insert, 'visual' is Vi-Visual
|
||||||
@@ -51,5 +68,10 @@ function fish_user_key_bindings
|
|||||||
bind --mode $mode ctrl-g __insert_previous_path_head
|
bind --mode $mode ctrl-g __insert_previous_path_head
|
||||||
bind --mode $mode ctrl-f __interactive_history_sub
|
bind --mode $mode ctrl-f __interactive_history_sub
|
||||||
bind --mode $mode ctrl-alt-u _replace_command_token
|
bind --mode $mode ctrl-alt-u _replace_command_token
|
||||||
|
type -q qalc && bind --mode $mode ctrl-alt-= _qalc_eval
|
||||||
|
bind --mode $mode ctrl-enter _smart_execute
|
||||||
|
bind --mode $mode @@ __fzf_inline_picker
|
||||||
|
bind --mode $mode ctrl-right nextd-or-forward-word
|
||||||
|
bind --mode $mode \e\[1\;5C nextd-or-forward-word
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# C5 — Logging & Capture: a non-blocking, per-session reminder shown inside Kitty
|
||||||
|
# when the fish-config scrollback watcher is not yet set up. It never blocks the
|
||||||
|
# shell; it simply prints how to enable or silence it. The notice stops once the
|
||||||
|
# user runs `kitty-logging install` (a watcher line then exists in kitty.conf) or
|
||||||
|
# `kitty-logging dismiss` (sets the universal variable below).
|
||||||
|
|
||||||
|
status is-interactive; or exit
|
||||||
|
type -q kitty; or exit
|
||||||
|
set -q KITTY_WINDOW_ID; or exit
|
||||||
|
__fish_config_op_enabled __fish_config_op_logging; or exit
|
||||||
|
__fish_variable_check __fish_config_kitty_watcher_dismissed; and exit
|
||||||
|
__kitty_logging_has_watcher; and exit
|
||||||
|
|
||||||
|
set_color --bold yellow
|
||||||
|
echo "Kitty session logging is available but not set up."
|
||||||
|
set_color normal
|
||||||
|
echo " Enable: kitty-logging install"
|
||||||
|
echo " Silence: kitty-logging dismiss"
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# C5 — Logging & Capture: registers --on-variable event handlers at shell
|
||||||
|
# startup so that changes to __fish_config_op_logging or the master
|
||||||
|
# __fish_config_opinionated take effect immediately in every running shell.
|
||||||
|
# Also calls __fish_config_sync_logging once to reconcile sentinel-file and
|
||||||
|
# wrapper state with any variable values that were pre-set before this shell
|
||||||
|
# started.
|
||||||
|
#
|
||||||
|
# These functions must be defined in conf.d (not functions/) because fish
|
||||||
|
# only autoloads from functions/ on explicit call — event handlers that live
|
||||||
|
# solely in functions/ are never registered and their --on-variable triggers
|
||||||
|
# never fire.
|
||||||
|
|
||||||
|
function __fish_config_logging_changed --on-variable __fish_config_op_logging \
|
||||||
|
--description 'C5 event handler: sync logging state when __fish_config_op_logging changes'
|
||||||
|
__fish_config_sync_logging
|
||||||
|
end
|
||||||
|
|
||||||
|
function __fish_config_opinionated_changed --on-variable __fish_config_opinionated \
|
||||||
|
--description 'C5 event handler: sync logging state when master opinionated switch changes'
|
||||||
|
__fish_config_sync_logging
|
||||||
|
end
|
||||||
|
|
||||||
|
# Sync once at startup so pre-set variable values take effect without a re-set
|
||||||
|
__fish_config_sync_logging
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
function magic-enter-cmd --description "Print the command to run when no command was given"
|
|
||||||
set -l cmd ls
|
|
||||||
if command git rev-parse --is-inside-work-tree &>/dev/null
|
|
||||||
set cmd "git status -sb"
|
|
||||||
end
|
|
||||||
echo $cmd
|
|
||||||
end
|
|
||||||
|
|
||||||
function magic-enter
|
|
||||||
set -l cmd (commandline)
|
|
||||||
if test -z "$cmd"
|
|
||||||
commandline -r (magic-enter-cmd)
|
|
||||||
commandline -f suppress-autosuggestion
|
|
||||||
end
|
|
||||||
commandline -f execute
|
|
||||||
end
|
|
||||||
|
|
||||||
function magic-enter-bindings --description "Bind magic-enter for default and vi key bindings"
|
|
||||||
bind \r magic-enter
|
|
||||||
if functions -q fish_vi_key_bindings
|
|
||||||
bind -M insert \r magic-enter
|
|
||||||
bind -M default \r magic-enter
|
|
||||||
end
|
|
||||||
end
|
|
||||||
magic-enter-bindings
|
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# Generates ~/.local/bin/paru on first run (and on version bump) when
|
||||||
|
# paru is installed. The wrapper runs paru in a PTY so progress
|
||||||
|
# bars are preserved, renders the captured animation to a clean static log
|
||||||
|
# (via scripts/clean_progress_log.py), and prunes old logs.
|
||||||
|
|
||||||
|
# Auto-generating a wrapper in ~/.local/bin is opinionated (C2 auto-exec).
|
||||||
|
# Wrapper generation is also gated by C5 (Logging & Capture).
|
||||||
|
__fish_config_op_enabled __fish_config_op_autoexec; or return
|
||||||
|
|
||||||
|
# C5 — Logging & Capture: remove generated wrapper and skip when logging is off
|
||||||
|
if not __fish_config_op_enabled __fish_config_op_logging
|
||||||
|
if test -f "$HOME/.local/bin/paru"
|
||||||
|
and grep -q "# paru-wrapper-version:" "$HOME/.local/bin/paru" 2>/dev/null
|
||||||
|
rm -f "$HOME/.local/bin/paru"
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# Resolve the real paru binary, skipping our own shim (never /usr/bin-assumed).
|
||||||
|
set -l _paru_real (__fish_real_command paru)
|
||||||
|
set -l _paru_wrapper "$HOME/.local/bin/paru"
|
||||||
|
set -l _paru_wrapper_version 6
|
||||||
|
|
||||||
|
# Skip entirely if the real paru binary isn't present
|
||||||
|
test -x "$_paru_real"; or return
|
||||||
|
|
||||||
|
# Check if wrapper already exists at the expected version
|
||||||
|
if test -f $_paru_wrapper
|
||||||
|
and grep -q "# paru-wrapper-version: $_paru_wrapper_version" $_paru_wrapper 2>/dev/null
|
||||||
|
set --erase _paru_real _paru_wrapper _paru_wrapper_version
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
mkdir -p (dirname $_paru_wrapper)
|
||||||
|
|
||||||
|
printf '%s\n' \
|
||||||
|
'#!/usr/bin/env bash' \
|
||||||
|
"# paru-wrapper-version: $_paru_wrapper_version" \
|
||||||
|
'# Auto-generated by conf.d/paru-wrapper.fish — do not edit by hand.' \
|
||||||
|
'# Runs paru in a PTY via script(1) so progress bars are preserved on screen,' \
|
||||||
|
'# then renders the captured terminal animation to a clean static log.' \
|
||||||
|
'' \
|
||||||
|
'log_dir="${SCROLLBACK_HISTORY_DIR:-$HOME/.terminal_history}"' \
|
||||||
|
'mkdir -p "$log_dir"' \
|
||||||
|
'log_file="$log_dir/paru_$(date +%Y-%m-%d_%H-%M-%S).log"' \
|
||||||
|
'' \
|
||||||
|
'# Build a safely-quoted command string for script(1).' \
|
||||||
|
'# script(1) allocates a PTY so paru detects a real terminal and shows progress.' \
|
||||||
|
"cmd_str=\"$_paru_real\"" \
|
||||||
|
'for arg in "$@"; do' \
|
||||||
|
' cmd_str+=" $(printf '"'"'%q'"'"' "$arg")"' \
|
||||||
|
'done' \
|
||||||
|
'script -q -e -c "$cmd_str" "$log_file"' \
|
||||||
|
'exit_code=$?' \
|
||||||
|
'' \
|
||||||
|
'# Render the captured terminal animation (progress bars repaint in place via' \
|
||||||
|
'# cursor moves) down to its final static frame, preserving ANSI color. Falls' \
|
||||||
|
'# back to dropping only the script(1) header/footer when python3 is missing.' \
|
||||||
|
'cleaner="${XDG_CONFIG_HOME:-$HOME/.config}/fish/scripts/clean_progress_log.py"' \
|
||||||
|
'if command -v python3 >/dev/null 2>&1 && [[ -f "$cleaner" ]]; then' \
|
||||||
|
' python3 "$cleaner" < "$log_file" > "${log_file}.tmp" 2>/dev/null && mv "${log_file}.tmp" "$log_file" || rm -f "${log_file}.tmp"' \
|
||||||
|
'else' \
|
||||||
|
' sed -i "/^Script \(started\|done\) on /d" "$log_file" 2>/dev/null || true' \
|
||||||
|
'fi' \
|
||||||
|
'' \
|
||||||
|
'max_files="${SCROLLBACK_HISTORY_MAX_FILES:-100}"' \
|
||||||
|
'mapfile -t logs < <(ls -1t "$log_dir"/paru_*.log 2>/dev/null)' \
|
||||||
|
'excess=$(( ${#logs[@]} - max_files ))' \
|
||||||
|
'for (( i = ${#logs[@]} - 1; i >= ${#logs[@]} - excess && i >= 0; i-- )); do' \
|
||||||
|
' rm -f "${logs[$i]}"' \
|
||||||
|
'done' \
|
||||||
|
'' \
|
||||||
|
'exit $exit_code' \
|
||||||
|
> $_paru_wrapper
|
||||||
|
|
||||||
|
chmod +x $_paru_wrapper
|
||||||
|
|
||||||
|
set --erase _paru_real _paru_wrapper _paru_wrapper_version
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
status is-interactive || exit
|
status is-interactive || exit
|
||||||
|
|
||||||
|
# Local modification: opinionated guard (AGENTS.md Task #3). Puffer's key
|
||||||
|
# intercepts are part of the bang-bang system, gated atomically under C3
|
||||||
|
# overrides with conf.d/tricks.fish, conf.d/abbr.fish, and expand_*.fish.
|
||||||
|
__fish_config_op_enabled __fish_config_op_overrides || exit
|
||||||
|
|
||||||
function _puffer_fish_key_bindings --on-variable fish_key_bindings
|
function _puffer_fish_key_bindings --on-variable fish_key_bindings
|
||||||
set -l modes
|
set -l modes
|
||||||
if test "$fish_key_bindings" = fish_default_key_bindings
|
if test "$fish_key_bindings" = fish_default_key_bindings
|
||||||
@@ -8,9 +13,21 @@ function _puffer_fish_key_bindings --on-variable fish_key_bindings
|
|||||||
set modes insert default
|
set modes insert default
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @category History Expansion
|
||||||
|
# @name !.
|
||||||
|
# @desc Expand .. to ../.. and so on
|
||||||
bind --mode $modes[1] '.' _puffer_fish_expand_dot
|
bind --mode $modes[1] '.' _puffer_fish_expand_dot
|
||||||
|
# @category History Expansion
|
||||||
|
# @name !!
|
||||||
|
# @desc Expand to the previous command
|
||||||
bind --mode $modes[1] '!' _puffer_fish_expand_bang
|
bind --mode $modes[1] '!' _puffer_fish_expand_bang
|
||||||
|
# @category History Expansion
|
||||||
|
# @name !$
|
||||||
|
# @desc Expand to the last argument of the previous command
|
||||||
bind --mode $modes[1] '$' _puffer_fish_expand_buck
|
bind --mode $modes[1] '$' _puffer_fish_expand_buck
|
||||||
|
# @category History Expansion
|
||||||
|
# @name !*
|
||||||
|
# @desc Expand to all arguments of the previous command
|
||||||
bind --mode $modes[1] '*' _puffer_fish_expand_star
|
bind --mode $modes[1] '*' _puffer_fish_expand_star
|
||||||
bind --mode $modes[2] --erase '.' '!' '$' '*'
|
bind --mode $modes[2] --erase '.' '!' '$' '*'
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,137 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
# ╭──────────────────────────────────────────────────────────╮
|
||||||
|
# │ Sponge Privacy Pattern Registration │
|
||||||
|
# ╰──────────────────────────────────────────────────────────╯
|
||||||
|
#
|
||||||
|
# Two-layer approach to keeping credentials out of shell history:
|
||||||
|
#
|
||||||
|
# Layer 1 — Static patterns (registered as universal, persistent):
|
||||||
|
# Covers structural signatures: auth flags, env var assignments,
|
||||||
|
# credential-bearing URLs, Authorization headers, sshpass, etc.
|
||||||
|
# Patterns are added idempotently; user additions are preserved.
|
||||||
|
#
|
||||||
|
# Layer 2 — Dynamic secret values (registered as session globals):
|
||||||
|
# On the first prompt (after secrets.fish has loaded), reads the
|
||||||
|
# literal values of all exported variables whose names indicate
|
||||||
|
# credentials (TOKEN, PASSWORD, SECRET, KEY, etc.) and adds them
|
||||||
|
# as a session-scoped pattern overlay. Refreshes automatically
|
||||||
|
# each login, so rotated tokens never leave stale patterns behind.
|
||||||
|
#
|
||||||
|
# Layer 3 — Per-command filter (sponge_filter_secrets):
|
||||||
|
# Catches mid-session variables set after login — e.g. a token
|
||||||
|
# exported interactively or sourced from a project .env file.
|
||||||
|
#
|
||||||
|
# To add your own persistent patterns:
|
||||||
|
# set -U -a sponge_regex_patterns 'your-regex-here'
|
||||||
|
|
||||||
|
if not status is-interactive
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# Only register if sponge is loaded
|
||||||
|
if not set -q sponge_version
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# ──────────────────── Layer 1: Static patterns ────────────────────
|
||||||
|
|
||||||
|
set -l _privacy_patterns
|
||||||
|
|
||||||
|
# Common auth flags with values: --password x, --token x, --passphrase x, --api-key x
|
||||||
|
# Use \- to avoid the pattern string starting with --, which string match
|
||||||
|
# would misinterpret as an unknown option flag.
|
||||||
|
set -a _privacy_patterns '\-\-(?:password|passwd|passphrase|token|secret|api[-_]key)(?:\s+|=)\S+'
|
||||||
|
|
||||||
|
# Inline env var assignments with sensitive names: GITHUB_TOKEN=xxx, MY_API_KEY=abc
|
||||||
|
set -a _privacy_patterns '(?i)\b[A-Z][A-Z0-9_]*(?:PASSWORD|PASSWD|SECRET|TOKEN|API_KEY|PRIVATE_KEY|ACCESS_KEY|AUTH_KEY|CREDENTIAL)[A-Z0-9_]*=\S+'
|
||||||
|
|
||||||
|
# Fish set with sensitive variable names: set -gx GITHUB_TOKEN xxx, set -U MY_SECRET yyy
|
||||||
|
set -a _privacy_patterns '(?i)set\s+-\S+\s+\S*(?:password|passwd|token|secret|api.?key|private.?key|access.?key|credential)\S*\s+\S+'
|
||||||
|
|
||||||
|
# URLs with embedded credentials: https://user:password@host
|
||||||
|
set -a _privacy_patterns 'https?://[^:@\s]+:[^@\s]+@'
|
||||||
|
|
||||||
|
# HTTP Authorization headers: curl -H "Authorization: Bearer xxx"
|
||||||
|
set -a _privacy_patterns 'curl\s.*[Aa]uthorization:'
|
||||||
|
|
||||||
|
# Basic auth flags: curl -u user:pass, wget --user user --password pass
|
||||||
|
set -a _privacy_patterns '(?:curl|wget)\s.*(?:-u|--user)\s+\S+:\S+'
|
||||||
|
|
||||||
|
# sshpass — exposes credentials as a CLI argument by design
|
||||||
|
set -a _privacy_patterns '\bsshpass\b'
|
||||||
|
|
||||||
|
# Docker login with inline password
|
||||||
|
set -a _privacy_patterns 'docker\s+login\s.*(?:-p|--password)\s+\S+'
|
||||||
|
|
||||||
|
# openssl passphrase arguments: -passin pass:xxx, -passout env:VAR
|
||||||
|
set -a _privacy_patterns 'openssl\s.*-pass(?:in|out)\s+\S+'
|
||||||
|
|
||||||
|
# Remove any previously stored patterns that begin with -- ; string match
|
||||||
|
# passes patterns before its own -- sentinel and would treat them as flags.
|
||||||
|
for _i in (seq (count $sponge_regex_patterns) -1 1)
|
||||||
|
if string match --quiet -- '--*' $sponge_regex_patterns[$_i]
|
||||||
|
set -Ue sponge_regex_patterns[$_i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Idempotent registration into universal sponge_regex_patterns
|
||||||
|
for _pattern in $_privacy_patterns
|
||||||
|
if not contains -- $_pattern $sponge_regex_patterns
|
||||||
|
set -U -a sponge_regex_patterns $_pattern
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# ──────────── Layer 2: Dynamic secret values (session globals) ────────────
|
||||||
|
|
||||||
|
# Runs once on the first prompt — by which point config.fish and secrets.fish
|
||||||
|
# have fully loaded, so all secret env vars are in scope.
|
||||||
|
# Builds a session-scoped global that combines the universal static patterns
|
||||||
|
# with the literal values of any credential-holding env vars. Globals shadow
|
||||||
|
# universals in Fish, so the combined list is what sponge sees for this session.
|
||||||
|
function __sponge_register_secret_values --on-event fish_prompt
|
||||||
|
functions --erase __sponge_register_secret_values # run exactly once
|
||||||
|
|
||||||
|
set -l secret_values
|
||||||
|
|
||||||
|
# Base credential-name tokens, plus any user-supplied extras from
|
||||||
|
# __fish_sponge_extra_sensitive (set via config-settings → Sponge page).
|
||||||
|
set -l _sensitive_names \
|
||||||
|
TOKEN PASSWORD PASSWD SECRET 'API[_-]KEY' 'PRIVATE[_-]KEY' \
|
||||||
|
'ACCESS[_-]KEY' 'AUTH[_-]KEY' CREDENTIAL KOPIA_PASSWORD \
|
||||||
|
$__fish_sponge_extra_sensitive
|
||||||
|
set -l _sensitive_alt (string join '|' $_sensitive_names)
|
||||||
|
|
||||||
|
# --entire returns the full matching variable NAME (e.g. GITHUB_TOKEN), not
|
||||||
|
# just the matched token substring (TOKEN) — required so $$var below
|
||||||
|
# dereferences the real variable instead of an unset partial name.
|
||||||
|
set -l sensitive_vars (set --names --export | string match --regex --entire -- \
|
||||||
|
"(?i)(?:$_sensitive_alt)")
|
||||||
|
|
||||||
|
for var in $sensitive_vars
|
||||||
|
# Take only the first element — array vars yield multiple values.
|
||||||
|
set -l value $$var[1]
|
||||||
|
# If the var is unset or holds an empty list, value has no elements;
|
||||||
|
# set -q catches that before string length receives zero arguments.
|
||||||
|
set -q value[1]; or continue
|
||||||
|
test (string length -- $value) -gt 8; or continue
|
||||||
|
string match --quiet --regex '^[/~]' -- $value; and continue
|
||||||
|
set -a secret_values (string escape --style=regex -- $value)
|
||||||
|
end
|
||||||
|
|
||||||
|
if test (count $secret_values) -gt 0
|
||||||
|
# Merge static universals + dynamic values into a session global
|
||||||
|
set -g sponge_regex_patterns $sponge_regex_patterns $secret_values
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# ──────────── Layer 3: Mid-session filter (sponge_filter_secrets) ─────────
|
||||||
|
|
||||||
|
# Catches credentials in variables exported after login (e.g. project .env files).
|
||||||
|
# Only register if not already in sponge_filters.
|
||||||
|
if functions --query sponge_filter_secrets
|
||||||
|
if not contains -- sponge_filter_secrets $sponge_filters
|
||||||
|
set -U -a sponge_filters sponge_filter_secrets
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# Defines fish_prompt only when starship is installed.
|
||||||
|
# Without starship, fish's built-in prompt already emits OSC 133;A
|
||||||
|
# on the prompt line itself, so no wrapper is needed.
|
||||||
|
|
||||||
|
# Replacing the prompt is opinionated (C3 overrides)
|
||||||
|
__fish_config_op_enabled __fish_config_op_overrides; or return
|
||||||
|
|
||||||
|
type -q starship; or return
|
||||||
|
|
||||||
|
function fish_prompt
|
||||||
|
set -l last_status $status
|
||||||
|
|
||||||
|
# Blank line between output and next prompt, skipped at the top of a cleared screen
|
||||||
|
if not test "$fish_private_mode" = true; and test (commandline) = ""
|
||||||
|
echo
|
||||||
|
end
|
||||||
|
|
||||||
|
# OSC 133;A here (after the blank line) puts the marker on the prompt line itself,
|
||||||
|
# not the blank line — required for ov's section-delimiter to pin the right line.
|
||||||
|
printf "\x1b]133;A\x07"
|
||||||
|
|
||||||
|
set -g STARSHIP_CMD_STATUS $last_status
|
||||||
|
command starship prompt --status=$last_status --pipestatus=$pipestatus --jobs=(count (jobs -p))
|
||||||
|
|
||||||
|
printf "\x1b]133;B\x07"
|
||||||
|
end
|
||||||
+20
-3
@@ -4,10 +4,19 @@
|
|||||||
# ╭──────────────────────────────────────────────────────────╮
|
# ╭──────────────────────────────────────────────────────────╮
|
||||||
# │ Fish Theme │
|
# │ Fish Theme │
|
||||||
# ╰──────────────────────────────────────────────────────────╯
|
# ╰──────────────────────────────────────────────────────────╯
|
||||||
#
|
# Catppuccin Mocha
|
||||||
# Catppuccin Mocha syntax highlighting colors.
|
|
||||||
# These variables were migrated from the universal scope to global scope.
|
|
||||||
|
|
||||||
|
# Forcing theme colors and $FZF_DEFAULT_OPTS is opinionated (C3 overrides).
|
||||||
|
# The FZF variable is universal, so clean up our Catppuccin value if it
|
||||||
|
# lingers from a session where overrides were still enabled.
|
||||||
|
if not __fish_config_op_enabled __fish_config_op_overrides
|
||||||
|
if set -q FZF_DEFAULT_OPTS; and string match -q '*#1E1E2E*' -- "$FZF_DEFAULT_OPTS"
|
||||||
|
set --erase FZF_DEFAULT_OPTS
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# ────────────────────── Syntax highlighting colors ──────────────────────
|
||||||
set --global fish_color_autosuggestion 6c7086
|
set --global fish_color_autosuggestion 6c7086
|
||||||
set --global fish_color_cancel f38ba8
|
set --global fish_color_cancel f38ba8
|
||||||
set --global fish_color_command 89b4fa
|
set --global fish_color_command 89b4fa
|
||||||
@@ -47,3 +56,11 @@ set --global fish_pager_color_selected_background
|
|||||||
set --global fish_pager_color_selected_completion
|
set --global fish_pager_color_selected_completion
|
||||||
set --global fish_pager_color_selected_description
|
set --global fish_pager_color_selected_description
|
||||||
set --global fish_pager_color_selected_prefix
|
set --global fish_pager_color_selected_prefix
|
||||||
|
|
||||||
|
# ─────────────────────────── FZF theme colors ───────────────────────────
|
||||||
|
set -Ux FZF_DEFAULT_OPTS "\
|
||||||
|
--color=bg+:#313244,bg:#1E1E2E,spinner:#F5E0DC,hl:#F38BA8 \
|
||||||
|
--color=fg:#CDD6F4,header:#F38BA8,info:#CBA6F7,pointer:#F5E0DC \
|
||||||
|
--color=marker:#B4BEFE,fg+:#CDD6F4,prompt:#CBA6F7,hl+:#F38BA8 \
|
||||||
|
--color=selected-bg:#45475A \
|
||||||
|
--color=border:#6C7086,label:#CDD6F4"
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# C5 — Logging & Capture: starts a pipe-pane log for the current tmux pane
|
||||||
|
# when fish launches inside a tmux session. Each fish shell gets its own
|
||||||
|
# timestamped log file in SCROLLBACK_HISTORY_DIR (default: ~/.terminal_history).
|
||||||
|
# Naming: tmux_<session>-w<window>-p<pane>_YYYY-MM-DD_HH-MM-SS.log
|
||||||
|
|
||||||
|
__fish_config_op_enabled __fish_config_op_logging; or exit
|
||||||
|
status is-interactive; or exit
|
||||||
|
type -q tmux; or exit
|
||||||
|
set -q TMUX; or exit
|
||||||
|
|
||||||
|
_tmux_pipe_log
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
# ────── Borrowed and modified from CachyOS config ─────────
|
||||||
|
# ╭──────────────────────────────────────────────────────────╮
|
||||||
|
# │ Provides PATH additions, bang-bang helpers, │
|
||||||
|
# │ system aliases, and history/backup utilities │
|
||||||
|
# ╰──────────────────────────────────────────────────────────╯
|
||||||
|
|
||||||
|
## Environment setup
|
||||||
|
# Apply .profile: use this to put fish compatible .profile stuff in
|
||||||
|
if test -f ~/.fish_profile
|
||||||
|
source ~/.fish_profile
|
||||||
|
end
|
||||||
|
|
||||||
|
# Append unique directories to $PATH (fish_add_path handles duplicates automatically)
|
||||||
|
fish_add_path ~/.local/bin
|
||||||
|
fish_add_path ~/Applications/depot_tools
|
||||||
|
|
||||||
|
# Expose user-local man pages
|
||||||
|
if not contains ~/.local/share/man $MANPATH
|
||||||
|
set -gx MANPATH ~/.local/share/man $MANPATH
|
||||||
|
end
|
||||||
|
|
||||||
|
# Format man pages using bat (only if bat is installed)
|
||||||
|
# Overriding $MANPAGER is opinionated (C3 overrides)
|
||||||
|
if type -q bat; and __fish_config_op_enabled __fish_config_op_overrides
|
||||||
|
set -gx MANROFFOPT -c
|
||||||
|
set -gx MANPAGER "sh -c 'col -bx | bat -l man -p'"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Set settings for https://github.com/franciscolourenco/done
|
||||||
|
set -gx __done_min_cmd_duration 10000
|
||||||
|
set -gx __done_notification_urgency_level low
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
# Functions needed for !! and !$ https://github.com/oh-my-fish/plugin-bang-bang
|
||||||
|
# The bang-bang system is opinionated (C3 overrides) and is gated atomically
|
||||||
|
# here, in conf.d/abbr.fish, conf.d/puffer.fish, and functions/expand_*.fish.
|
||||||
|
if __fish_config_op_enabled __fish_config_op_overrides
|
||||||
|
function __history_previous_command
|
||||||
|
switch (commandline -t)
|
||||||
|
case "!"
|
||||||
|
commandline -t $history[1]
|
||||||
|
commandline -f repaint
|
||||||
|
case "*"
|
||||||
|
commandline -i !
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function __history_previous_command_arguments
|
||||||
|
switch (commandline -t)
|
||||||
|
case "!"
|
||||||
|
commandline -t ""
|
||||||
|
commandline -f history-token-search-backward
|
||||||
|
case "*"
|
||||||
|
commandline -i '$'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Apply bang-bang key bindings based on current key binding mode
|
||||||
|
if [ "$fish_key_bindings" = fish_vi_key_bindings ]
|
||||||
|
# @category History Expansion
|
||||||
|
# @name !!
|
||||||
|
# @desc Expand to the previous command
|
||||||
|
bind -Minsert ! __history_previous_command
|
||||||
|
# @category History Expansion
|
||||||
|
# @name !$
|
||||||
|
# @desc Expand to the last argument of the previous command
|
||||||
|
bind -Minsert '$' __history_previous_command_arguments
|
||||||
|
else
|
||||||
|
# @category History Expansion
|
||||||
|
# @name !!
|
||||||
|
# @desc Expand to the previous command
|
||||||
|
bind ! __history_previous_command
|
||||||
|
# @category History Expansion
|
||||||
|
# @name !$
|
||||||
|
# @desc Expand to the last argument of the previous command
|
||||||
|
bind '$' __history_previous_command_arguments
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Fish command history override to show timestamps
|
||||||
|
# Shadowing the history command is opinionated (C1 aliasing); when disabled,
|
||||||
|
# the function is never defined and fish's stock history behavior applies.
|
||||||
|
if __fish_config_op_enabled __fish_config_op_aliases
|
||||||
|
function history
|
||||||
|
builtin history --show-time='%F %T '
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Quick file backup utility
|
||||||
|
function backup --argument filename
|
||||||
|
cp $filename $filename.bak
|
||||||
|
end
|
||||||
|
|
||||||
|
# Memory monitoring helpers
|
||||||
|
function psmem
|
||||||
|
ps auxf | sort -nr -k 4
|
||||||
|
end
|
||||||
|
|
||||||
|
function psmem10
|
||||||
|
ps auxf | sort -nr -k 4 | head -10
|
||||||
|
end
|
||||||
|
|
||||||
|
## Useful aliases
|
||||||
|
|
||||||
|
# Navigation short-cuts
|
||||||
|
# @category Shell Aliases
|
||||||
|
# @desc cd ..
|
||||||
|
alias ..='cd ..'
|
||||||
|
# @category Shell Aliases
|
||||||
|
# @desc cd ../..
|
||||||
|
alias ...='cd ../..'
|
||||||
|
# @category Shell Aliases
|
||||||
|
# @desc cd ../../..
|
||||||
|
alias ....='cd ../../..'
|
||||||
|
# @category Shell Aliases
|
||||||
|
# @desc cd ../../../..
|
||||||
|
alias .....='cd ../../../..'
|
||||||
|
# @category Shell Aliases
|
||||||
|
# @desc cd ../../../../..
|
||||||
|
alias ......='cd ../../../../..'
|
||||||
|
|
||||||
|
# Silent flag injection into POSIX tools is opinionated (C1 aliasing)
|
||||||
|
if __fish_config_op_enabled __fish_config_op_aliases
|
||||||
|
# Tools & Core command color overrides
|
||||||
|
# @category Shell Aliases
|
||||||
|
# @desc dir --color=auto
|
||||||
|
alias dir='dir --color=auto'
|
||||||
|
# @category Shell Aliases
|
||||||
|
# @desc vdir --color=auto
|
||||||
|
alias vdir='vdir --color=auto'
|
||||||
|
# @category Shell Aliases
|
||||||
|
# @desc grep --color=auto
|
||||||
|
alias grep='grep --color=auto'
|
||||||
|
# @category Shell Aliases
|
||||||
|
# @desc fgrep --color=auto
|
||||||
|
alias fgrep='fgrep --color=auto'
|
||||||
|
# @category Shell Aliases
|
||||||
|
# @desc egrep --color=auto
|
||||||
|
alias egrep='egrep --color=auto'
|
||||||
|
|
||||||
|
# Safety aliases (Confirmation before overwriting/deleting)
|
||||||
|
# @category Shell Aliases
|
||||||
|
# @desc cp -i
|
||||||
|
alias cp="cp -i"
|
||||||
|
# @category Shell Aliases
|
||||||
|
# @desc mv -i
|
||||||
|
alias mv="mv -i"
|
||||||
|
|
||||||
|
# Force wget to resume partial downloads
|
||||||
|
alias wget='wget -c '
|
||||||
|
end
|
||||||
|
|
||||||
|
# Archives and networking short-hands
|
||||||
|
# @category Shell Aliases
|
||||||
|
# @desc tar -acf
|
||||||
|
alias tarnow='tar -acf '
|
||||||
|
# @category Shell Aliases
|
||||||
|
# @desc tar -zxvf
|
||||||
|
alias untar='tar -zxvf '
|
||||||
|
# @category Shell Aliases
|
||||||
|
# @desc nc termbin.com 9999
|
||||||
|
alias tb='nc termbin.com 9999'
|
||||||
|
|
||||||
|
# System Logs
|
||||||
|
# @category Shell Aliases
|
||||||
|
# @desc journalctl -p 3 -xb
|
||||||
|
alias jctl="journalctl -p 3 -xb"
|
||||||
@@ -5,6 +5,12 @@
|
|||||||
# see: https://github.com/ik11235/wakatime.fish
|
# see: https://github.com/ik11235/wakatime.fish
|
||||||
###
|
###
|
||||||
|
|
||||||
|
# Local modification: opinionated guard (AGENTS.md Task #3). WakaTime
|
||||||
|
# reporting is classified under both C2 auto-execution and C4 integrations;
|
||||||
|
# disabling either category skips registering the hook.
|
||||||
|
__fish_config_op_enabled __fish_config_op_autoexec; or exit
|
||||||
|
__fish_config_op_enabled __fish_config_op_integrations; or exit
|
||||||
|
|
||||||
function __register_wakatime_fish_before_exec -e fish_postexec
|
function __register_wakatime_fish_before_exec -e fish_postexec
|
||||||
if set -q FISH_WAKATIME_DISABLED
|
if set -q FISH_WAKATIME_DISABLED
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# Generates ~/.local/bin/yay on first run (and on version bump) when
|
||||||
|
# yay is installed. The wrapper runs yay in a PTY so progress
|
||||||
|
# bars are preserved, renders the captured animation to a clean static log
|
||||||
|
# (via scripts/clean_progress_log.py), and prunes old logs.
|
||||||
|
|
||||||
|
# Auto-generating a wrapper in ~/.local/bin is opinionated (C2 auto-exec).
|
||||||
|
# Wrapper generation is also gated by C5 (Logging & Capture).
|
||||||
|
__fish_config_op_enabled __fish_config_op_autoexec; or return
|
||||||
|
|
||||||
|
# C5 — Logging & Capture: remove generated wrapper and skip when logging is off
|
||||||
|
if not __fish_config_op_enabled __fish_config_op_logging
|
||||||
|
if test -f "$HOME/.local/bin/yay"
|
||||||
|
and grep -q "# yay-wrapper-version:" "$HOME/.local/bin/yay" 2>/dev/null
|
||||||
|
rm -f "$HOME/.local/bin/yay"
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# Resolve the real yay binary, skipping our own shim (never /usr/bin-assumed).
|
||||||
|
set -l _yay_real (__fish_real_command yay)
|
||||||
|
set -l _yay_wrapper "$HOME/.local/bin/yay"
|
||||||
|
set -l _yay_wrapper_version 6
|
||||||
|
|
||||||
|
# Skip entirely if the real yay binary isn't present
|
||||||
|
test -x "$_yay_real"; or return
|
||||||
|
|
||||||
|
# Check if wrapper already exists at the expected version
|
||||||
|
if test -f $_yay_wrapper
|
||||||
|
and grep -q "# yay-wrapper-version: $_yay_wrapper_version" $_yay_wrapper 2>/dev/null
|
||||||
|
set --erase _yay_real _yay_wrapper _yay_wrapper_version
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
mkdir -p (dirname $_yay_wrapper)
|
||||||
|
|
||||||
|
printf '%s\n' \
|
||||||
|
'#!/usr/bin/env bash' \
|
||||||
|
"# yay-wrapper-version: $_yay_wrapper_version" \
|
||||||
|
'# Auto-generated by conf.d/yay-wrapper.fish — do not edit by hand.' \
|
||||||
|
'# Runs yay in a PTY via script(1) so progress bars are preserved on screen,' \
|
||||||
|
'# then renders the captured terminal animation to a clean static log.' \
|
||||||
|
'' \
|
||||||
|
'log_dir="${SCROLLBACK_HISTORY_DIR:-$HOME/.terminal_history}"' \
|
||||||
|
'mkdir -p "$log_dir"' \
|
||||||
|
'log_file="$log_dir/yay_$(date +%Y-%m-%d_%H-%M-%S).log"' \
|
||||||
|
'' \
|
||||||
|
'# Build a safely-quoted command string for script(1).' \
|
||||||
|
'# script(1) allocates a PTY so yay detects a real terminal and shows progress.' \
|
||||||
|
"cmd_str=\"$_yay_real\"" \
|
||||||
|
'for arg in "$@"; do' \
|
||||||
|
' cmd_str+=" $(printf '"'"'%q'"'"' "$arg")"' \
|
||||||
|
'done' \
|
||||||
|
'script -q -e -c "$cmd_str" "$log_file"' \
|
||||||
|
'exit_code=$?' \
|
||||||
|
'' \
|
||||||
|
'# Render the captured terminal animation (progress bars repaint in place via' \
|
||||||
|
'# cursor moves) down to its final static frame, preserving ANSI color. Falls' \
|
||||||
|
'# back to dropping only the script(1) header/footer when python3 is missing.' \
|
||||||
|
'cleaner="${XDG_CONFIG_HOME:-$HOME/.config}/fish/scripts/clean_progress_log.py"' \
|
||||||
|
'if command -v python3 >/dev/null 2>&1 && [[ -f "$cleaner" ]]; then' \
|
||||||
|
' python3 "$cleaner" < "$log_file" > "${log_file}.tmp" 2>/dev/null && mv "${log_file}.tmp" "$log_file" || rm -f "${log_file}.tmp"' \
|
||||||
|
'else' \
|
||||||
|
' sed -i "/^Script \(started\|done\) on /d" "$log_file" 2>/dev/null || true' \
|
||||||
|
'fi' \
|
||||||
|
'' \
|
||||||
|
'max_files="${SCROLLBACK_HISTORY_MAX_FILES:-100}"' \
|
||||||
|
'mapfile -t logs < <(ls -1t "$log_dir"/yay_*.log 2>/dev/null)' \
|
||||||
|
'excess=$(( ${#logs[@]} - max_files ))' \
|
||||||
|
'for (( i = ${#logs[@]} - 1; i >= ${#logs[@]} - excess && i >= 0; i-- )); do' \
|
||||||
|
' rm -f "${logs[$i]}"' \
|
||||||
|
'done' \
|
||||||
|
'' \
|
||||||
|
'exit $exit_code' \
|
||||||
|
> $_yay_wrapper
|
||||||
|
|
||||||
|
chmod +x $_yay_wrapper
|
||||||
|
|
||||||
|
set --erase _yay_real _yay_wrapper _yay_wrapper_version
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# C5 — Logging & Capture: registers a fish_exit handler that dumps the current
|
||||||
|
# Zellij pane's scrollback to a log file when the shell exits. Unlike tmux
|
||||||
|
# (streamed live via pipe-pane), Zellij has no continuous-capture facility, so
|
||||||
|
# we snapshot once on exit via `zellij action dump-screen --full`.
|
||||||
|
#
|
||||||
|
# The handler is registered whenever fish runs inside Zellij; the C5 logging
|
||||||
|
# guard is evaluated inside _zellij_dump_log at exit time, so toggling
|
||||||
|
# __fish_config_op_logging takes effect on the next exit without a restart
|
||||||
|
# (no sync_logging coordination needed, since there is no live stream to stop).
|
||||||
|
#
|
||||||
|
# Event-handler functions must be defined at startup (conf.d) so the --on-event
|
||||||
|
# binding is registered; autoloaded functions in functions/ never register.
|
||||||
|
|
||||||
|
status is-interactive; or exit
|
||||||
|
type -q zellij; or exit
|
||||||
|
set -q ZELLIJ; or exit
|
||||||
|
|
||||||
|
function __zellij_dump_on_exit --on-event fish_exit \
|
||||||
|
--description 'C5 event handler: dump Zellij pane scrollback on shell exit'
|
||||||
|
_zellij_dump_log
|
||||||
|
end
|
||||||
+78
-97
@@ -1,106 +1,87 @@
|
|||||||
# =============================================================================
|
# Copyright (C) 2026 Rootiest
|
||||||
#
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
#
|
# Adapted from icezyclon/zoxide.fish (MIT)
|
||||||
# Utility functions for zoxide.
|
# Heavily customized for Fish 4.x compatibility and performance
|
||||||
#
|
|
||||||
|
|
||||||
if not type -q zoxide
|
if status is-interactive
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
# pwd based on the value of _ZO_RESOLVE_SYMLINKS.
|
if type -q zoxide
|
||||||
function __zoxide_pwd
|
|
||||||
builtin pwd -L
|
|
||||||
end
|
|
||||||
|
|
||||||
# A copy of fish's internal cd function. This makes it possible to use
|
# -------------
|
||||||
# `alias cd=z` without causing an infinite loop.
|
# 'zoxide init fish' is very different for different versions of zoxide
|
||||||
if ! builtin functions --query __zoxide_cd_internal
|
# to guarantee the same behavior we define these functions ourself,
|
||||||
string replace --regex -- '^function cd\s' 'function __zoxide_cd_internal ' <$__fish_data_dir/functions/cd.fish | source
|
# especially because the apt package is so old
|
||||||
end
|
# most of these functions were taken from https://github.com/ajeetdsouza/zoxide
|
||||||
|
# from version 0.8.1
|
||||||
|
|
||||||
# cd + custom logic based on the value of _ZO_ECHO.
|
if ! builtin functions -q _zoxide_cd
|
||||||
function __zoxide_cd
|
if builtin functions -q cd
|
||||||
if set -q __zoxide_loop
|
builtin functions -c cd _zoxide_cd
|
||||||
builtin echo "zoxide: infinite loop detected"
|
else
|
||||||
builtin echo "Avoid aliasing `cd` to `z` directly, use `zoxide init --cmd=cd fish` instead"
|
alias _zoxide_cd='builtin cd'
|
||||||
return 1
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function _zoxide_hook --on-variable PWD
|
||||||
|
test -z "$fish_private_mode"
|
||||||
|
and command zoxide add -- (builtin pwd -L)
|
||||||
|
end
|
||||||
|
|
||||||
|
function z
|
||||||
|
set argc (count $argv)
|
||||||
|
if test $argc -eq 0
|
||||||
|
_zoxide_cd $HOME
|
||||||
|
else if test "$argv" = -
|
||||||
|
_zoxide_cd -
|
||||||
|
else
|
||||||
|
# Check if the argument is a directory (respecting CDPATH)
|
||||||
|
set -l is_dir 1
|
||||||
|
if test -d $argv[-1]
|
||||||
|
set is_dir 0
|
||||||
|
else if not string match -rq '^\.?\.?/' -- $argv[-1]
|
||||||
|
for i in $CDPATH
|
||||||
|
if test -n "$i" -a -d "$i/$argv[-1]"
|
||||||
|
set is_dir 0
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if test $is_dir -eq 0
|
||||||
|
_zoxide_cd $argv[-1]
|
||||||
|
else
|
||||||
|
set -l result (command zoxide query -- $argv)
|
||||||
|
and _zoxide_cd $result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function zi
|
||||||
|
set -l result (command zoxide query -i -- $argv)
|
||||||
|
and _zoxide_cd $result
|
||||||
|
end
|
||||||
|
|
||||||
|
# -------------
|
||||||
|
|
||||||
|
# Shadowing cd with zoxide is opinionated (C1 aliasing); z and zi
|
||||||
|
# remain available either way.
|
||||||
|
if __fish_config_op_enabled __fish_config_op_aliases
|
||||||
|
alias cd=z
|
||||||
|
end
|
||||||
|
|
||||||
|
# use custom completion
|
||||||
|
complete -c z -f # disable files by default
|
||||||
|
complete -c z -x -a '(_zoxide_z_complete)'
|
||||||
end
|
end
|
||||||
__zoxide_loop=1 __zoxide_cd_internal $argv
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# =============================================================================
|
function _zoxide_uninstall --on-event zoxide_uninstall
|
||||||
#
|
if alias | grep "alias cd z" >/dev/null
|
||||||
# Hook configuration for zoxide.
|
functions -e cd
|
||||||
#
|
end
|
||||||
|
if builtin functions -q _zoxide_cd && not functions -q cd
|
||||||
# Initialize hook to add new entries to the database.
|
# restore old cd
|
||||||
function __zoxide_hook --on-variable PWD
|
builtin functions -c _zoxide_cd cd
|
||||||
test -z "$fish_private_mode"
|
|
||||||
and command zoxide add -- (__zoxide_pwd)
|
|
||||||
end
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
#
|
|
||||||
# When using zoxide with --no-cmd, alias these internal functions as desired.
|
|
||||||
#
|
|
||||||
|
|
||||||
# Jump to a directory using only keywords.
|
|
||||||
function __zoxide_z
|
|
||||||
set -l argc (builtin count $argv)
|
|
||||||
if test $argc -eq 0
|
|
||||||
__zoxide_cd $HOME
|
|
||||||
else if test "$argv" = -
|
|
||||||
__zoxide_cd -
|
|
||||||
else if test $argc -eq 1 -a -d $argv[1]
|
|
||||||
__zoxide_cd $argv[1]
|
|
||||||
else if test $argc -eq 2 -a $argv[1] = --
|
|
||||||
__zoxide_cd -- $argv[2]
|
|
||||||
else
|
|
||||||
set -l result (command zoxide query --exclude (__zoxide_pwd) -- $argv)
|
|
||||||
and __zoxide_cd $result
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Completions.
|
|
||||||
function __zoxide_z_complete
|
|
||||||
set -l tokens (builtin commandline --current-process --tokenize)
|
|
||||||
set -l curr_tokens (builtin commandline --cut-at-cursor --current-process --tokenize)
|
|
||||||
|
|
||||||
if test (builtin count $tokens) -le 2 -a (builtin count $curr_tokens) -eq 1
|
|
||||||
# If there are < 2 arguments, use `cd` completions.
|
|
||||||
complete --do-complete "'' "(builtin commandline --cut-at-cursor --current-token) | string match --regex -- '.*/$'
|
|
||||||
else if test (builtin count $tokens) -eq (builtin count $curr_tokens)
|
|
||||||
# If the last argument is empty, use interactive selection.
|
|
||||||
set -l query $tokens[2..-1]
|
|
||||||
set -l result (command zoxide query --exclude (__zoxide_pwd) --interactive -- $query)
|
|
||||||
and __zoxide_cd $result
|
|
||||||
and builtin commandline --function cancel-commandline repaint
|
|
||||||
end
|
|
||||||
end
|
|
||||||
complete --command __zoxide_z --no-files --arguments '(__zoxide_z_complete)'
|
|
||||||
|
|
||||||
# Jump to a directory using interactive search.
|
|
||||||
function __zoxide_zi
|
|
||||||
set -l result (command zoxide query --interactive -- $argv)
|
|
||||||
and __zoxide_cd $result
|
|
||||||
end
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
#
|
|
||||||
# Commands for zoxide. Disable these using --no-cmd.
|
|
||||||
#
|
|
||||||
|
|
||||||
abbr --erase z &>/dev/null
|
|
||||||
alias z=__zoxide_z
|
|
||||||
|
|
||||||
abbr --erase zi &>/dev/null
|
|
||||||
alias zi=__zoxide_zi
|
|
||||||
|
|
||||||
abbr --erase cdi &>/dev/null
|
|
||||||
alias cdi=__zoxide_zi
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
# Initialize zoxide:
|
|
||||||
|
|
||||||
zoxide init --cmd=cd fish | source
|
|
||||||
|
|||||||
+249
-112
@@ -5,133 +5,270 @@
|
|||||||
# │ Fish Configuration │
|
# │ Fish Configuration │
|
||||||
# ╰──────────────────────────────────────────────────────────╯
|
# ╰──────────────────────────────────────────────────────────╯
|
||||||
|
|
||||||
|
# ───────────────────── Opinionated component guards ─────────────────────
|
||||||
|
# Opinionated components (AGENTS.md Task #3) are wrapped in
|
||||||
|
# __fish_config_op_enabled <category> guards throughout this file and conf.d/.
|
||||||
|
# The helper always evaluates the master switch __fish_config_opinionated
|
||||||
|
# first (falsy disables everything), then the per-category opt-out variable:
|
||||||
|
# __fish_config_op_aliases C1 — command shadows / flag injection
|
||||||
|
# __fish_config_op_autoexec C2 — startup side-effects
|
||||||
|
# __fish_config_op_overrides C3 — key bindings, env, prompt overrides
|
||||||
|
# __fish_config_op_integrations C4 — terminal/tool coupling
|
||||||
|
# __fish_config_op_logging C5 — scrollback capture / AUR log wrappers
|
||||||
|
# (opt-in: unset means OFF)
|
||||||
|
# __fish_config_op_greeting C6 — per-session greeting / first-run welcome
|
||||||
|
# Example: set -U __fish_config_op_aliases off (erase to re-enable)
|
||||||
|
# C5 is the one exception: it defaults to disabled and needs an explicit
|
||||||
|
# truthy value — set -U __fish_config_op_logging on
|
||||||
|
|
||||||
# ──────────────────────── Source CachyOS configs ────────────────────────
|
# ──────────────────────── Source CachyOS configs ────────────────────────
|
||||||
if test -f /usr/share/cachyos-fish-config/cachyos-config.fish
|
if test -f /usr/share/cachyos-fish-config/cachyos-config.fish
|
||||||
source /usr/share/cachyos-fish-config/cachyos-config.fish
|
source /usr/share/cachyos-fish-config/cachyos-config.fish
|
||||||
# CachyOS defines aliases for ls/lt/cleanup that shadow our function files.
|
# Surgically overriding the distro config is opinionated (C3 overrides):
|
||||||
# Erase them and immediately source our versions.
|
# skip it entirely when overrides are disabled, keeping CachyOS defaults.
|
||||||
for _fname in ls lt cleanup
|
if __fish_config_op_enabled __fish_config_op_overrides
|
||||||
functions --erase $_fname
|
# Source our tricks over the cachyOS config
|
||||||
source $__fish_config_dir/functions/$_fname.fish
|
test -f "$__fish_config_dir/conf.d/tricks.fish"
|
||||||
|
and source "$__fish_config_dir/conf.d/tricks.fish"
|
||||||
|
# Erase CachyOS aliases/functions that shadow our versions, then
|
||||||
|
# re-source our versions since functions --erase removes autoload entries.
|
||||||
|
for _fname in ls lt cleanup copy
|
||||||
|
functions --erase $_fname
|
||||||
|
source "$__fish_config_dir/functions/$_fname.fish"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# The distro config ships opinionated pieces of its own (it is the origin
|
||||||
|
# of tricks.fish); strip them when the matching category is disabled so
|
||||||
|
# the guards hold on CachyOS systems too.
|
||||||
|
if not __fish_config_op_enabled __fish_config_op_aliases
|
||||||
|
for _fname in grep fgrep egrep dir vdir wget
|
||||||
|
functions -q $_fname; and functions --erase $_fname
|
||||||
|
end
|
||||||
|
# Restore fish's stock versions where they exist (erasing alone would
|
||||||
|
# also block autoloading the stock function).
|
||||||
|
for _fname in history ls
|
||||||
|
functions -q $_fname; and functions --erase $_fname
|
||||||
|
test -f $__fish_data_dir/functions/$_fname.fish
|
||||||
|
and source $__fish_data_dir/functions/$_fname.fish
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not __fish_config_op_enabled __fish_config_op_overrides
|
||||||
|
for _fname in __history_previous_command __history_previous_command_arguments
|
||||||
|
functions -q $_fname; and functions --erase $_fname
|
||||||
|
end
|
||||||
|
bind --erase ! 2>/dev/null
|
||||||
|
bind --erase '$' 2>/dev/null
|
||||||
|
bind -M insert --erase ! 2>/dev/null
|
||||||
|
bind -M insert --erase '$' 2>/dev/null
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
set --erase _fname
|
set --erase _fname
|
||||||
|
|
||||||
# ──────────────────────────── Bootstrap Fisher ──────────────────────────
|
# ───────────────────────────── XDG variables ────────────────────────────
|
||||||
if not type -q fisher
|
# XDG Base Directory variables (standard practice)
|
||||||
echo "Fisher plugin manager not found."
|
# We set these unconditionally to ensure a consistent baseline, but only if
|
||||||
read -l -P "Install Fisher and plugins now? [Y/n] " _fisher_reply
|
# they are not already defined by the system/user.
|
||||||
if test -z "$_fisher_reply" -o "$_fisher_reply" = Y -o "$_fisher_reply" = y
|
set -q XDG_CONFIG_HOME; or set -gx XDG_CONFIG_HOME $HOME/.config # Sets default config dir to ~/.config
|
||||||
echo "Installing Fisher..."
|
set -q XDG_CACHE_HOME; or set -gx XDG_CACHE_HOME $HOME/.cache # Sets default cache dir to ~/.cache
|
||||||
curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source
|
set -q XDG_DATA_HOME; or set -gx XDG_DATA_HOME $HOME/.local/share # Sets default data dir to ~/.local/share
|
||||||
fisher update
|
set -q XDG_STATE_HOME; or set -gx XDG_STATE_HOME $HOME/.local/state # Sets default state dir to ~/.local/state
|
||||||
fish_config theme choose "Catppuccin Mocha"
|
|
||||||
else
|
# Attempt to keep various config/cache files out of the home directory root
|
||||||
echo "Skipping Fisher install. Some features may be unavailable."
|
set -q RANDFILE; or set -gx RANDFILE "$XDG_STATE_HOME/rnd"
|
||||||
|
set -q WGETRC; or set -gx WGETRC "$XDG_CONFIG_HOME/wget/wgetrc"
|
||||||
|
set -q WGET_HSTS_FILE; or set -gx WGET_HSTS_FILE "$XDG_CACHE_HOME/wget-hsts"
|
||||||
|
set -q NPM_CONFIG_PREFIX; or set -gx NPM_CONFIG_PREFIX "$XDG_DATA_HOME/npm-global"
|
||||||
|
set -q NPM_CONFIG_USERCONFIG; or set -gx NPM_CONFIG_USERCONFIG "$XDG_CONFIG_HOME/npm/npmrc"
|
||||||
|
set -q ANDROID_USER_HOME; or set -gx ANDROID_USER_HOME "$XDG_DATA_HOME/android"
|
||||||
|
set -q CARGO_HOME; or set -gx CARGO_HOME "$XDG_DATA_HOME/cargo"
|
||||||
|
set -q RUSTUP_HOME; or set -gx RUSTUP_HOME "$XDG_DATA_HOME/rustup"
|
||||||
|
set -q GOPATH; or set -gx GOPATH "$XDG_DATA_HOME/go"
|
||||||
|
set -q BUN_INSTALL; or set -gx BUN_INSTALL "$XDG_DATA_HOME/bun"
|
||||||
|
set -q GNUPGHOME; or set -gx GNUPGHOME "$XDG_CONFIG_HOME/gnupg"
|
||||||
|
set -q WAKATIME_HOME; or set -gx WAKATIME_HOME "$XDG_CONFIG_HOME/wakatime"
|
||||||
|
set -q HISTFILE; or set -gx HISTFILE "$XDG_STATE_HOME/bash_history"
|
||||||
|
set -q EXINIT; or set -gx EXINIT "set viminfofile=$XDG_STATE_HOME/vim/viminfo | source $MYVIMRC"
|
||||||
|
set -q NVIDIA_SETTINGS_RW_CONFIG_FILE; or set -gx NVIDIA_SETTINGS_RW_CONFIG_FILE "$XDG_CONFIG_HOME/nvidia/settings"
|
||||||
|
set -q CODEIUM_HOME; or set -gx CODEIUM_HOME "$XDG_CONFIG_HOME/codeium"
|
||||||
|
set -q WORDLIST; or set -gx WORDLIST "$XDG_CONFIG_HOME/hunspell_en_US"
|
||||||
|
|
||||||
|
# ─────────────────────────── Pager variables ────────────────────────────
|
||||||
|
# Overriding $PAGER, $EDITOR, and $GPG_TTY is opinionated (C3 overrides)
|
||||||
|
if __fish_config_op_enabled __fish_config_op_overrides
|
||||||
|
if type -q ov
|
||||||
|
set -gx PAGER ov
|
||||||
|
else if type -q less
|
||||||
|
set -gx PAGER less
|
||||||
end
|
end
|
||||||
set --erase _fisher_reply
|
|
||||||
|
# ─────────────────────────── Editor variables ───────────────────────────
|
||||||
|
# Set Editor variables with fallback to vi if nvim isn't available. This ensures that
|
||||||
|
# tools that rely on these variables (like git commit messages) will work out of the box,
|
||||||
|
# while still preferring nvim if it's installed.
|
||||||
|
if type -q nvim
|
||||||
|
set -gx NVIM_APPNAME nvim
|
||||||
|
set -gx EDITOR (command -s nvim)
|
||||||
|
else
|
||||||
|
set -gx EDITOR (command -s vi)
|
||||||
|
end
|
||||||
|
# set -gx VISUAL $EDITOR # <- Use local.fish to set your preferred GUI editor.
|
||||||
|
set -gx SUDO_EDITOR $EDITOR
|
||||||
|
|
||||||
|
# ──────────────────────────── GPG variables ─────────────────────────────
|
||||||
|
# Helps ensure that GPG can prompt for passphrases correctly when invoked from the terminal.
|
||||||
|
set -gx GPG_TTY (tty)
|
||||||
end
|
end
|
||||||
|
|
||||||
# ───────────────────────── Source user secrets ──────────────────────────
|
# ────────────────────────── Scrollback History ──────────────────────────
|
||||||
if test -f $HOME/.config/.user-dots/fish/secrets.fish
|
# Optional fish-style source of truth (set -U via config-settings); exported
|
||||||
source $HOME/.config/.user-dots/fish/secrets.fish
|
# for the POSIX wrappers (paru/yay/tmux/zellij/_prune_terminal_logs) that read
|
||||||
end
|
# them. We export the default unconditionally, then override from the universal
|
||||||
|
# var only if set — deliberately NOT creating a global, which would shadow the
|
||||||
|
# universal and stop live edits (config-settings → Paths) from taking effect.
|
||||||
|
set -gx SCROLLBACK_HISTORY_DIR "$HOME/.terminal_history"
|
||||||
|
set -q __fish_scrollback_history_dir
|
||||||
|
and set -gx SCROLLBACK_HISTORY_DIR $__fish_scrollback_history_dir
|
||||||
|
|
||||||
# ─────────────────────── Source machine-local config ─────────────────────
|
set -gx SCROLLBACK_HISTORY_MAX_FILES 100
|
||||||
if test -f $HOME/.config/.user-dots/fish/local.fish
|
set -q __fish_scrollback_history_max_files
|
||||||
source $HOME/.config/.user-dots/fish/local.fish
|
and set -gx SCROLLBACK_HISTORY_MAX_FILES $__fish_scrollback_history_max_files
|
||||||
|
# Wire up a clean exit function that won't fire on background subshells
|
||||||
|
# Replacing the exit builtin is opinionated (C3 overrides); smart_exit also
|
||||||
|
# guards itself so a live toggle takes effect without restarting the shell.
|
||||||
|
if status is-interactive; and __fish_config_op_enabled __fish_config_op_overrides
|
||||||
|
function exit --description 'Safe interactive exit'
|
||||||
|
# If the smart_exit file exists in our function path, invoke it explicitly
|
||||||
|
if functions -q smart_exit
|
||||||
|
smart_exit $argv
|
||||||
|
else
|
||||||
|
# Absolute fallback to protect shell mechanics
|
||||||
|
builtin exit $argv
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# ──────────────────────────── PATH variables ────────────────────────────
|
# ──────────────────────────── PATH variables ────────────────────────────
|
||||||
fish_add_path ~/.local/bin
|
# Adds common user bin directories to the PATH. The -mg --move option for cargo ensures that
|
||||||
fish_add_path ~/Applications
|
# the cargo bin directory is moved to the end of the PATH, which can help avoid conflicts
|
||||||
fish_add_path ~/scripts
|
# with system-installed Rust tools while still allowing user-installed cargo binaries to be found.
|
||||||
fish_add_path -mg --move ~/.cargo/bin
|
# PATH setup is opinionated (C3 overrides)
|
||||||
fish_add_path ~/.npm-global/bin
|
if __fish_config_op_enabled __fish_config_op_overrides
|
||||||
fish_add_path ~/.lmstudio/bin
|
fish_add_path $HOME/.local/bin # Standard user-local executables (XDG spec)
|
||||||
|
fish_add_path $HOME/.local/share/../bin # Alternative/legacy path for local user binaries
|
||||||
# ─────────────────────────── Editor variables ───────────────────────────
|
fish_add_path $HOME/Applications # User-installed applications and standalone apps
|
||||||
if command -v nvim >/dev/null
|
fish_add_path $HOME/scripts # Custom personal shell scripts and automation
|
||||||
set -gx EDITOR (command -s nvim)
|
fish_add_path -mga $CARGO_HOME/bin # Rust binaries and tools installed via Cargo
|
||||||
else
|
fish_add_path $BUN_INSTALL/bin # Bun runtime executables and globally installed packages
|
||||||
set -gx EDITOR (command -s vi)
|
fish_add_path $XDG_DATA_HOME/npm-global/bin # Global Node.js/npm packages (XDG compliant location)
|
||||||
|
fish_add_path $HOME/.lmstudio/bin # LM Studio CLI tools for local LLM management
|
||||||
|
fish_add_path $HOME/.resend/bin # Resend email service CLI tools
|
||||||
|
fish_add_path $HOME/.fzf/bin # Fuzzy Finder (fzf) core binary and helper scripts
|
||||||
end
|
end
|
||||||
set -gx VISUAL $EDITOR
|
|
||||||
set -gx SUDO_EDITOR $EDITOR
|
|
||||||
|
|
||||||
# ──────────────────────────── GPG variables ─────────────────────────────
|
|
||||||
set -gx GPG_TTY (tty)
|
|
||||||
|
|
||||||
# ────────────────────────────── Key bindings ────────────────────────────
|
|
||||||
set -g fish_key_bindings fish_vi_key_bindings
|
|
||||||
|
|
||||||
# ──────────────────────── Source FZF integration ────────────────────────
|
|
||||||
source ~/.config/fish/integrations/fzf.fish
|
|
||||||
# Configure FZF theme
|
|
||||||
set -Ux FZF_DEFAULT_OPTS "\
|
|
||||||
--color=bg+:#313244,bg:#1E1E2E,spinner:#F5E0DC,hl:#F38BA8 \
|
|
||||||
--color=fg:#CDD6F4,header:#F38BA8,info:#CBA6F7,pointer:#F5E0DC \
|
|
||||||
--color=marker:#B4BEFE,fg+:#CDD6F4,prompt:#CBA6F7,hl+:#F38BA8 \
|
|
||||||
--color=selected-bg:#45475A \
|
|
||||||
--color=border:#6C7086,label:#CDD6F4"
|
|
||||||
|
|
||||||
# ──────────────────────────────── DirENV ────────────────────────────────
|
|
||||||
# Tool to handle automatic environment loading in directories and their children
|
|
||||||
# Use when children need to load venv as well.
|
|
||||||
#
|
|
||||||
# The Auto-Venv script above will ignore directories with a
|
|
||||||
# .envrc file (direnv configuration) to prevent conflicts.
|
|
||||||
if type -q direnv
|
|
||||||
direnv hook fish | source
|
|
||||||
end
|
|
||||||
|
|
||||||
# ────────────────────────────── Auto-Venv ───────────────────────────────
|
|
||||||
# Auto-activate Python venv on directory change
|
|
||||||
function __auto_source_fallback_venv --on-variable PWD
|
|
||||||
status --is-command-substitution; and return
|
|
||||||
|
|
||||||
# 1. Skip if direnv is already managing this directory
|
|
||||||
if set -q DIRENV_DIR; or test -e ".envrc"
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
# 2. If we are already in a venv, check if we've left its tree
|
|
||||||
if set -q VIRTUAL_ENV
|
|
||||||
# Check if the current PWD is still within the directory that owns the venv
|
|
||||||
# (Assuming the venv is at the root of the project)
|
|
||||||
set -l venv_root (string replace -r '/.venv$' '' $VIRTUAL_ENV)
|
|
||||||
if not string match -q "$venv_root*" "$PWD"
|
|
||||||
type -q deactivate; and deactivate
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
# 3. Only source the venv if we aren't already in one
|
|
||||||
if test -e ".venv/bin/activate.fish"
|
|
||||||
source .venv/bin/activate.fish
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# ──────────────────── Docker Contexts for LazyDocker ────────────────────
|
|
||||||
function ld --description 'Run lazydocker on the current Docker context'
|
|
||||||
# Fetch the host endpoint of the currently active Docker context
|
|
||||||
set -l current_host (docker context inspect --format '{{.Endpoints.docker.Host}}')
|
|
||||||
|
|
||||||
# Run lazydocker with the DOCKER_HOST variable set for this command only
|
|
||||||
env DOCKER_HOST=$current_host lazydocker
|
|
||||||
end
|
|
||||||
|
|
||||||
# ────────────────────── Claude Code Env Variables ───────────────────────
|
|
||||||
set -gx CLAUDE_CODE_NO_FLICKER 1
|
|
||||||
|
|
||||||
# ───────────────────── Directory shortcut variables ─────────────────────
|
|
||||||
set -U cdp ~/projects
|
|
||||||
|
|
||||||
# ───────────────────────── CDPATH projects dir ──────────────────────────
|
# ───────────────────────── CDPATH projects dir ──────────────────────────
|
||||||
# Allows cd-ing to projects automatically from anywhere
|
# Allows cd-ing to directories within $HOME/projects or $HOME without needing to specify the full path.
|
||||||
set -U CDPATH . ~/projects ~
|
# For example, if you have a project at $HOME/projects/myproject,
|
||||||
|
# you can simply run 'cd myproject' from anywhere and it will take you there.
|
||||||
|
# 'cd' command prioritizes directories in CDPATH, so if you have a directory with
|
||||||
|
# the same name in both $HOME/projects and $HOME, it will take you to the one in $HOME/projects first.
|
||||||
|
# Additionally, directories inside the CWD will still take precedence over CDPATH,
|
||||||
|
# so if you have a directory named 'myproject' in the current directory,
|
||||||
|
# running 'cd myproject' will take you there instead of $HOME/projects/myproject.
|
||||||
|
# CDPATH injection is opinionated (C3 overrides)
|
||||||
|
if __fish_config_op_enabled __fish_config_op_overrides
|
||||||
|
set -gx CDPATH . $HOME/projects $HOME
|
||||||
|
end
|
||||||
|
|
||||||
# ─────────────────────────── Starship prompt ────────────────────────────
|
# ──────────────────────────── Bootstrap Fisher ──────────────────────────
|
||||||
# STARSHIP_START
|
# Fisher is bootstrapped automatically on first run via conf.d/first_run.fish
|
||||||
starship init fish | source
|
|
||||||
# STARSHIP_END
|
# ─────────────────────── Visual/Interactive setup ───────────────────────
|
||||||
|
# Run only if we're in an interactive session (not a script or non-interactive shell)
|
||||||
|
if status is-interactive
|
||||||
|
# ────────────────────────────── Key bindings ────────────────────────────
|
||||||
|
# Helps ensure that key bindings are consistent with the Vi editing mode set below.
|
||||||
|
# This is optional but can improve the user experience for those who prefer Vi-style key bindings.
|
||||||
|
# Global Vi mode is opinionated (C3 overrides); without it fish keeps its
|
||||||
|
# default Emacs-style bindings.
|
||||||
|
if __fish_config_op_enabled __fish_config_op_overrides
|
||||||
|
set -g fish_key_bindings fish_vi_key_bindings
|
||||||
|
end
|
||||||
|
|
||||||
|
# ──────────────────────── Source FZF integration ────────────────────────
|
||||||
|
# Prefer fzf's own fish integration (fzf --fish, available since fzf 0.48)
|
||||||
|
# which is always version-matched to the installed binary. Fall back to our
|
||||||
|
# bundled integrations/fzf.fish for older builds.
|
||||||
|
# Run `fzf-update` to install/upgrade fzf from git HEAD.
|
||||||
|
if type -q fzf
|
||||||
|
set -l _fzf_minor (fzf --version | string match -r '^\d+\.(\d+)')[2]
|
||||||
|
if test -n "$_fzf_minor" -a "$_fzf_minor" -ge 48
|
||||||
|
fzf --fish | source
|
||||||
|
else
|
||||||
|
test -f "$__fish_config_dir/integrations/fzf.fish"
|
||||||
|
and source "$__fish_config_dir/integrations/fzf.fish"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
# conf.d/fzf.fish is managed by Fisher and may be restored on fisher
|
||||||
|
# update, so this is the reliable place to strip its bindings when
|
||||||
|
# fzf is not installed.
|
||||||
|
functions -q _fzf_uninstall_bindings; and _fzf_uninstall_bindings
|
||||||
|
end
|
||||||
|
|
||||||
|
# ──────────────────────────────── DirENV ────────────────────────────────
|
||||||
|
# Tool to handle automatic environment loading in directories and their children
|
||||||
|
# Use when children need to load venv as well.
|
||||||
|
#
|
||||||
|
# The Auto-Venv script above will ignore directories with a
|
||||||
|
# .envrc file (direnv configuration) to prevent conflicts.
|
||||||
|
type -q direnv; and direnv hook fish | source
|
||||||
|
|
||||||
|
# Helps ensure that Claude Code's terminal output is clean and doesn't have flickering issues.
|
||||||
|
set -gx CLAUDE_CODE_NO_FLICKER 1
|
||||||
|
|
||||||
|
# ╭────────────────────────────── OVERRIDES ─────────────────────────────╮
|
||||||
|
# │ Run these last so they can override any previous settings. │
|
||||||
|
# │ This is useful for machine-specific behavior or configurations. │
|
||||||
|
# ╰────────────────────────────── OVERRIDES ─────────────────────────────╯
|
||||||
|
#
|
||||||
|
# Resolve user-dots path. Customize via: set -U __fish_user_dots_path /your/path
|
||||||
|
set -q __fish_user_dots_path
|
||||||
|
or set -l __fish_user_dots_path "$XDG_CONFIG_HOME/.user-dots/fish"
|
||||||
|
# ────────────────────── user-dots convenience symlink ───────────────────
|
||||||
|
# Keep $__fish_config_dir/user-dots tracking the resolved path so it can be
|
||||||
|
# browsed from the fish config dir. Git-ignored. Controlled by the
|
||||||
|
# __fish_user_dots_symlink toggle (config-settings → Paths); creation is a
|
||||||
|
# C2 side-effect, removal-on-opt-out is honoured regardless. See the helper.
|
||||||
|
__fish_user_dots_link
|
||||||
|
|
||||||
|
# ─────────────────────── Source machine-local config ────────────────────
|
||||||
|
# Sources local.fish if it exists. That file handles sourcing its own
|
||||||
|
# secrets.fish companion when needed.
|
||||||
|
test -f "$__fish_user_dots_path/local.fish"; and source "$__fish_user_dots_path/local.fish"
|
||||||
|
|
||||||
|
# ─────────────────── C6: Greeting & First-Run UI override ───────────────
|
||||||
|
# When the greeting category is disabled, stamp out any fish_greeting
|
||||||
|
# function that distro configs set (e.g., CachyOS defines it as fastfetch).
|
||||||
|
# This runs last inside the interactive block so our empty definition wins
|
||||||
|
# over whatever cachyos-config.fish or vendor conf.d installed.
|
||||||
|
if not __fish_config_op_enabled __fish_config_op_greeting
|
||||||
|
function fish_greeting
|
||||||
|
end
|
||||||
|
end
|
||||||
|
#
|
||||||
|
# ╭──────────────────────────── END OVERRIDES ──────────────────────────╮
|
||||||
|
# │ End of override section. │
|
||||||
|
# ╰──────────────────────────── END OVERRIDES ──────────────────────────╯
|
||||||
|
end
|
||||||
|
|
||||||
|
return # <-- Do not remove this line.
|
||||||
|
# ╭──────────────────────────────── !!!NOTE!!! ───────────────────────────────╮
|
||||||
|
# │ Tools like starship, zoxide, etc. append init lines below this point │
|
||||||
|
# │ via their setup commands. We manage these integrations through │
|
||||||
|
# │ conf.d/ instead, so we return here to prevent duplicate or conflicting │
|
||||||
|
# │ inits from being executed. │
|
||||||
|
# │ │
|
||||||
|
# │ If a tool's shell integration appears to do nothing, │
|
||||||
|
# │ check whether its setup command appended an init line here, │
|
||||||
|
# │ then create a conf.d/<tool>.fish instead and place the init in that file. │
|
||||||
|
# ╰───────────────────────────────────────────────────────────────────────────╯
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
admiring
|
||||||
|
adoring
|
||||||
|
affectionate
|
||||||
|
agitated
|
||||||
|
amazing
|
||||||
|
angry
|
||||||
|
awesome
|
||||||
|
beautiful
|
||||||
|
blissful
|
||||||
|
bold
|
||||||
|
boring
|
||||||
|
brave
|
||||||
|
busy
|
||||||
|
charming
|
||||||
|
clever
|
||||||
|
compassionate
|
||||||
|
competent
|
||||||
|
condescending
|
||||||
|
confident
|
||||||
|
cool
|
||||||
|
cranky
|
||||||
|
crazy
|
||||||
|
dazzling
|
||||||
|
determined
|
||||||
|
distracted
|
||||||
|
dreamy
|
||||||
|
eager
|
||||||
|
ecstatic
|
||||||
|
elastic
|
||||||
|
elated
|
||||||
|
elegant
|
||||||
|
eloquent
|
||||||
|
epic
|
||||||
|
exciting
|
||||||
|
fervent
|
||||||
|
festive
|
||||||
|
flamboyant
|
||||||
|
focused
|
||||||
|
friendly
|
||||||
|
frosty
|
||||||
|
funny
|
||||||
|
gallant
|
||||||
|
gifted
|
||||||
|
goofy
|
||||||
|
gracious
|
||||||
|
great
|
||||||
|
happy
|
||||||
|
hardcore
|
||||||
|
heuristic
|
||||||
|
hopeful
|
||||||
|
hungry
|
||||||
|
infallible
|
||||||
|
inspiring
|
||||||
|
intelligent
|
||||||
|
interesting
|
||||||
|
jolly
|
||||||
|
jovial
|
||||||
|
keen
|
||||||
|
kind
|
||||||
|
laughing
|
||||||
|
loving
|
||||||
|
lucid
|
||||||
|
magical
|
||||||
|
modest
|
||||||
|
musing
|
||||||
|
mystifying
|
||||||
|
naughty
|
||||||
|
nervous
|
||||||
|
nice
|
||||||
|
nifty
|
||||||
|
nostalgic
|
||||||
|
objective
|
||||||
|
optimistic
|
||||||
|
peaceful
|
||||||
|
pedantic
|
||||||
|
pensive
|
||||||
|
practical
|
||||||
|
priceless
|
||||||
|
quirky
|
||||||
|
quizzical
|
||||||
|
recursing
|
||||||
|
relaxed
|
||||||
|
reverent
|
||||||
|
romantic
|
||||||
|
sad
|
||||||
|
serene
|
||||||
|
sharp
|
||||||
|
silly
|
||||||
|
sleepy
|
||||||
|
stoic
|
||||||
|
strange
|
||||||
|
stupefied
|
||||||
|
suspicious
|
||||||
|
sweet
|
||||||
|
tender
|
||||||
|
thirsty
|
||||||
|
trusting
|
||||||
|
unruffled
|
||||||
|
upbeat
|
||||||
|
vibrant
|
||||||
|
vigilant
|
||||||
|
vigorous
|
||||||
|
wizardly
|
||||||
|
wonderful
|
||||||
|
xenodochial
|
||||||
|
youthful
|
||||||
|
zealous
|
||||||
|
zen
|
||||||
@@ -0,0 +1,223 @@
|
|||||||
|
aardvark
|
||||||
|
albatross
|
||||||
|
alligator
|
||||||
|
alpaca
|
||||||
|
ant
|
||||||
|
anteater
|
||||||
|
antelope
|
||||||
|
ape
|
||||||
|
armadillo
|
||||||
|
baboon
|
||||||
|
badger
|
||||||
|
barracuda
|
||||||
|
bat
|
||||||
|
bear
|
||||||
|
beaver
|
||||||
|
bee
|
||||||
|
bison
|
||||||
|
boar
|
||||||
|
buffalo
|
||||||
|
butterfly
|
||||||
|
camel
|
||||||
|
capybara
|
||||||
|
caribou
|
||||||
|
cat
|
||||||
|
caterpillar
|
||||||
|
cattle
|
||||||
|
chamois
|
||||||
|
cheetah
|
||||||
|
chicken
|
||||||
|
chimpanzee
|
||||||
|
chinchilla
|
||||||
|
chough
|
||||||
|
clam
|
||||||
|
cobra
|
||||||
|
cockroach
|
||||||
|
cod
|
||||||
|
cormorant
|
||||||
|
coyote
|
||||||
|
crab
|
||||||
|
crane
|
||||||
|
crocodile
|
||||||
|
crow
|
||||||
|
curlew
|
||||||
|
deer
|
||||||
|
dinosaur
|
||||||
|
dog
|
||||||
|
dogfish
|
||||||
|
dolphin
|
||||||
|
donkey
|
||||||
|
dotterel
|
||||||
|
dove
|
||||||
|
dragonfly
|
||||||
|
duck
|
||||||
|
dugong
|
||||||
|
dunlin
|
||||||
|
eagle
|
||||||
|
echidna
|
||||||
|
eel
|
||||||
|
eland
|
||||||
|
elephant
|
||||||
|
elk
|
||||||
|
emu
|
||||||
|
falcon
|
||||||
|
ferret
|
||||||
|
finch
|
||||||
|
fish
|
||||||
|
flamingo
|
||||||
|
fly
|
||||||
|
fox
|
||||||
|
frog
|
||||||
|
gaur
|
||||||
|
gazelle
|
||||||
|
gerbil
|
||||||
|
giraffe
|
||||||
|
gnat
|
||||||
|
gnu
|
||||||
|
goat
|
||||||
|
goldfinch
|
||||||
|
goldfish
|
||||||
|
goose
|
||||||
|
gorilla
|
||||||
|
goshawk
|
||||||
|
grasshopper
|
||||||
|
grouse
|
||||||
|
guanaco
|
||||||
|
gull
|
||||||
|
hamster
|
||||||
|
hare
|
||||||
|
hawk
|
||||||
|
hedgehog
|
||||||
|
heron
|
||||||
|
herring
|
||||||
|
hippopotamus
|
||||||
|
hornet
|
||||||
|
horse
|
||||||
|
human
|
||||||
|
hummingbird
|
||||||
|
hyena
|
||||||
|
ibex
|
||||||
|
ibis
|
||||||
|
jackal
|
||||||
|
jaguar
|
||||||
|
jay
|
||||||
|
jellyfish
|
||||||
|
kangaroo
|
||||||
|
kingfisher
|
||||||
|
koala
|
||||||
|
kookabura
|
||||||
|
kouprey
|
||||||
|
kudu
|
||||||
|
lapwing
|
||||||
|
lark
|
||||||
|
lemur
|
||||||
|
leopard
|
||||||
|
lion
|
||||||
|
llama
|
||||||
|
lobster
|
||||||
|
locust
|
||||||
|
loris
|
||||||
|
louse
|
||||||
|
lyrebird
|
||||||
|
magpie
|
||||||
|
mallard
|
||||||
|
manatee
|
||||||
|
mandrill
|
||||||
|
mantis
|
||||||
|
marten
|
||||||
|
meerkat
|
||||||
|
mink
|
||||||
|
mole
|
||||||
|
mongoose
|
||||||
|
monkey
|
||||||
|
moose
|
||||||
|
mosquito
|
||||||
|
mouse
|
||||||
|
mule
|
||||||
|
narwhal
|
||||||
|
newt
|
||||||
|
nightingale
|
||||||
|
octopus
|
||||||
|
okapi
|
||||||
|
opossum
|
||||||
|
oryx
|
||||||
|
ostrich
|
||||||
|
otter
|
||||||
|
owl
|
||||||
|
oyster
|
||||||
|
panther
|
||||||
|
parrot
|
||||||
|
partridge
|
||||||
|
peafowl
|
||||||
|
pelican
|
||||||
|
penguin
|
||||||
|
pheasant
|
||||||
|
pig
|
||||||
|
pigeon
|
||||||
|
pony
|
||||||
|
porcupine
|
||||||
|
porpoise
|
||||||
|
quail
|
||||||
|
quelea
|
||||||
|
quetzal
|
||||||
|
rabbit
|
||||||
|
raccoon
|
||||||
|
rail
|
||||||
|
ram
|
||||||
|
rat
|
||||||
|
raven
|
||||||
|
red-deer
|
||||||
|
red-panda
|
||||||
|
reindeer
|
||||||
|
rhinoceros
|
||||||
|
rook
|
||||||
|
salamander
|
||||||
|
salmon
|
||||||
|
sand-dollar
|
||||||
|
sandpiper
|
||||||
|
sardine
|
||||||
|
scorpion
|
||||||
|
seahorse
|
||||||
|
seal
|
||||||
|
shark
|
||||||
|
sheep
|
||||||
|
shrew
|
||||||
|
skunk
|
||||||
|
snail
|
||||||
|
snake
|
||||||
|
sparrow
|
||||||
|
spider
|
||||||
|
spoonbill
|
||||||
|
squid
|
||||||
|
squirrel
|
||||||
|
starling
|
||||||
|
stingray
|
||||||
|
stinkbug
|
||||||
|
stork
|
||||||
|
swallow
|
||||||
|
swan
|
||||||
|
tapir
|
||||||
|
tarsier
|
||||||
|
termite
|
||||||
|
tiger
|
||||||
|
toad
|
||||||
|
trout
|
||||||
|
turkey
|
||||||
|
turtle
|
||||||
|
viper
|
||||||
|
vulture
|
||||||
|
wallaby
|
||||||
|
walrus
|
||||||
|
wasp
|
||||||
|
weasel
|
||||||
|
whale
|
||||||
|
wildcat
|
||||||
|
wolf
|
||||||
|
wolverine
|
||||||
|
wombat
|
||||||
|
woodcock
|
||||||
|
woodpecker
|
||||||
|
worm
|
||||||
|
wren
|
||||||
|
yak
|
||||||
|
zebra
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
amber
|
||||||
|
amethyst
|
||||||
|
apricot
|
||||||
|
aqua
|
||||||
|
aquamarine
|
||||||
|
auburn
|
||||||
|
azure
|
||||||
|
beige
|
||||||
|
black
|
||||||
|
blue
|
||||||
|
bronze
|
||||||
|
brown
|
||||||
|
buff
|
||||||
|
carmine
|
||||||
|
celadon
|
||||||
|
cerise
|
||||||
|
cerulean
|
||||||
|
charcoal
|
||||||
|
chartreuse
|
||||||
|
chocolate
|
||||||
|
cinnamon
|
||||||
|
copper
|
||||||
|
coral
|
||||||
|
cream
|
||||||
|
crimson
|
||||||
|
cyan
|
||||||
|
denim
|
||||||
|
emerald
|
||||||
|
fuchsia
|
||||||
|
gold
|
||||||
|
goldenrod
|
||||||
|
gray
|
||||||
|
green
|
||||||
|
grey
|
||||||
|
indigo
|
||||||
|
ivory
|
||||||
|
jade
|
||||||
|
khaki
|
||||||
|
lavender
|
||||||
|
lemon
|
||||||
|
lilac
|
||||||
|
lime
|
||||||
|
magenta
|
||||||
|
mahogany
|
||||||
|
maroon
|
||||||
|
mauve
|
||||||
|
mustard
|
||||||
|
navy
|
||||||
|
ochre
|
||||||
|
olive
|
||||||
|
orange
|
||||||
|
orchid
|
||||||
|
peach
|
||||||
|
pear
|
||||||
|
periwinkle
|
||||||
|
pink
|
||||||
|
plum
|
||||||
|
puce
|
||||||
|
purple
|
||||||
|
quartz
|
||||||
|
red
|
||||||
|
rose
|
||||||
|
ruby
|
||||||
|
rust
|
||||||
|
salmon
|
||||||
|
sapphire
|
||||||
|
scarlet
|
||||||
|
silver
|
||||||
|
slate
|
||||||
|
tan
|
||||||
|
taupe
|
||||||
|
teal
|
||||||
|
tomato
|
||||||
|
topaz
|
||||||
|
turquoise
|
||||||
|
ultramarine
|
||||||
|
umber
|
||||||
|
vanilla
|
||||||
|
violet
|
||||||
|
white
|
||||||
|
yellow
|
||||||
@@ -0,0 +1,236 @@
|
|||||||
|
agnesi
|
||||||
|
albattani
|
||||||
|
allen
|
||||||
|
almeida
|
||||||
|
antonelli
|
||||||
|
archimedes
|
||||||
|
ardinghelli
|
||||||
|
aryabhata
|
||||||
|
austin
|
||||||
|
babbage
|
||||||
|
banach
|
||||||
|
banzai
|
||||||
|
bardeen
|
||||||
|
bartik
|
||||||
|
bassi
|
||||||
|
beaver
|
||||||
|
bell
|
||||||
|
benz
|
||||||
|
bhabha
|
||||||
|
bhaskara
|
||||||
|
black
|
||||||
|
blackburn
|
||||||
|
blackwell
|
||||||
|
bohr
|
||||||
|
booth
|
||||||
|
borg
|
||||||
|
bose
|
||||||
|
bouman
|
||||||
|
boyd
|
||||||
|
brahmagupta
|
||||||
|
brattain
|
||||||
|
brown
|
||||||
|
buck
|
||||||
|
burnell
|
||||||
|
cannon
|
||||||
|
carson
|
||||||
|
cartwright
|
||||||
|
carver
|
||||||
|
cerf
|
||||||
|
chandrasekhar
|
||||||
|
chaplygin
|
||||||
|
chatelet
|
||||||
|
chatterjee
|
||||||
|
chaum
|
||||||
|
chebyshev
|
||||||
|
clarke
|
||||||
|
cohen
|
||||||
|
colden
|
||||||
|
cori
|
||||||
|
cray
|
||||||
|
curie
|
||||||
|
curran
|
||||||
|
darwin
|
||||||
|
davinci
|
||||||
|
dewdney
|
||||||
|
dhawan
|
||||||
|
diffie
|
||||||
|
dijkstra
|
||||||
|
dirac
|
||||||
|
driscoll
|
||||||
|
dubinsky
|
||||||
|
easley
|
||||||
|
edison
|
||||||
|
einstein
|
||||||
|
elbakyan
|
||||||
|
elgamal
|
||||||
|
elion
|
||||||
|
ellis
|
||||||
|
engelbart
|
||||||
|
euclid
|
||||||
|
euler
|
||||||
|
faraday
|
||||||
|
feistel
|
||||||
|
fermat
|
||||||
|
fermi
|
||||||
|
feynman
|
||||||
|
franklin
|
||||||
|
gagarin
|
||||||
|
galileo
|
||||||
|
galois
|
||||||
|
ganguly
|
||||||
|
gates
|
||||||
|
gauss
|
||||||
|
germain
|
||||||
|
goldberg
|
||||||
|
goldstine
|
||||||
|
goldwasser
|
||||||
|
golick
|
||||||
|
goodall
|
||||||
|
gould
|
||||||
|
greider
|
||||||
|
grothendieck
|
||||||
|
haibt
|
||||||
|
hamilton
|
||||||
|
haslett
|
||||||
|
hawking
|
||||||
|
heisenberg
|
||||||
|
hellman
|
||||||
|
hermann
|
||||||
|
herschel
|
||||||
|
hertz
|
||||||
|
heyrovsky
|
||||||
|
hodgkin
|
||||||
|
hofstadter
|
||||||
|
hoover
|
||||||
|
hopper
|
||||||
|
hugle
|
||||||
|
hypatia
|
||||||
|
ishizaka
|
||||||
|
jackson
|
||||||
|
jang
|
||||||
|
jemison
|
||||||
|
jennings
|
||||||
|
jepsen
|
||||||
|
johnson
|
||||||
|
joliot
|
||||||
|
jones
|
||||||
|
kalam
|
||||||
|
kapitsa
|
||||||
|
kare
|
||||||
|
keldysh
|
||||||
|
keller
|
||||||
|
kepler
|
||||||
|
khayyam
|
||||||
|
khorana
|
||||||
|
kilby
|
||||||
|
kirch
|
||||||
|
knuth
|
||||||
|
kowalevski
|
||||||
|
lalande
|
||||||
|
lamarr
|
||||||
|
lamport
|
||||||
|
leakey
|
||||||
|
leavitt
|
||||||
|
lederberg
|
||||||
|
lehmann
|
||||||
|
lewin
|
||||||
|
lichterman
|
||||||
|
liskov
|
||||||
|
lovelace
|
||||||
|
lumiere
|
||||||
|
mahavira
|
||||||
|
margulis
|
||||||
|
matsumoto
|
||||||
|
maxwell
|
||||||
|
mayer
|
||||||
|
mccarthy
|
||||||
|
mcclintock
|
||||||
|
mclaren
|
||||||
|
mclean
|
||||||
|
mcnulty
|
||||||
|
meitner
|
||||||
|
mendel
|
||||||
|
mendeleev
|
||||||
|
meninsky
|
||||||
|
merkle
|
||||||
|
mestorf
|
||||||
|
mirzakhani
|
||||||
|
montalcini
|
||||||
|
moore
|
||||||
|
morse
|
||||||
|
moser
|
||||||
|
murdock
|
||||||
|
napier
|
||||||
|
nash
|
||||||
|
neumann
|
||||||
|
newton
|
||||||
|
nightingale
|
||||||
|
nobel
|
||||||
|
noether
|
||||||
|
northcutt
|
||||||
|
noyce
|
||||||
|
panini
|
||||||
|
pare
|
||||||
|
pascal
|
||||||
|
pasteur
|
||||||
|
payne
|
||||||
|
perlman
|
||||||
|
pike
|
||||||
|
poincare
|
||||||
|
poitras
|
||||||
|
proskuriakova
|
||||||
|
ptolemy
|
||||||
|
raman
|
||||||
|
ramanujan
|
||||||
|
rhodes
|
||||||
|
ride
|
||||||
|
ritchie
|
||||||
|
robinson
|
||||||
|
roentgen
|
||||||
|
rosalind
|
||||||
|
rubin
|
||||||
|
saha
|
||||||
|
sammet
|
||||||
|
sanderson
|
||||||
|
satoshi
|
||||||
|
shamir
|
||||||
|
shannon
|
||||||
|
shaw
|
||||||
|
shirley
|
||||||
|
shockley
|
||||||
|
shtern
|
||||||
|
sinoussi
|
||||||
|
snyder
|
||||||
|
solomon
|
||||||
|
spence
|
||||||
|
stonebraker
|
||||||
|
sutherland
|
||||||
|
swanson
|
||||||
|
swartz
|
||||||
|
swirles
|
||||||
|
taussig
|
||||||
|
tesla
|
||||||
|
tharp
|
||||||
|
thompson
|
||||||
|
torvalds
|
||||||
|
tu
|
||||||
|
turing
|
||||||
|
varahamihira
|
||||||
|
vaughan
|
||||||
|
villani
|
||||||
|
visvesvaraya
|
||||||
|
volhard
|
||||||
|
wescoff
|
||||||
|
wilbur
|
||||||
|
wiles
|
||||||
|
williams
|
||||||
|
williamson
|
||||||
|
wilson
|
||||||
|
wing
|
||||||
|
wozniak
|
||||||
|
wright
|
||||||
|
wu
|
||||||
|
yalow
|
||||||
|
yonath
|
||||||
|
zhukovsky
|
||||||
+1296
File diff suppressed because it is too large
Load Diff
+1000
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,862 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
"""Generate publishable artifacts from the docs/manual SSOT.
|
||||||
|
|
||||||
|
--concat one ordered markdown document for pandoc / config-help
|
||||||
|
--site Starlight content tree + sidebar.json
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import manualtools as mt
|
||||||
|
|
||||||
|
DOCS = Path(__file__).parent
|
||||||
|
MANUAL = DOCS / "manual"
|
||||||
|
FUNCTIONS = DOCS.parent / "functions"
|
||||||
|
SLUG_DIR = "reference"
|
||||||
|
|
||||||
|
|
||||||
|
def _is_function_page(path: Path, root: Path) -> bool:
|
||||||
|
"""True for a Section 5 category stub (not its index)."""
|
||||||
|
rel = path.relative_to(root)
|
||||||
|
return bool(rel.parts) and rel.parts[0].endswith("-functions") and rel.name != "index.md"
|
||||||
|
|
||||||
|
|
||||||
|
def _entry_slug(title: str) -> str:
|
||||||
|
"""The site's page slug for an entry heading."""
|
||||||
|
return re.sub(r"[^\w-]+", "-", title.strip().lower()).strip("-")
|
||||||
|
|
||||||
|
|
||||||
|
def _entry_link(name: str, functions: dict) -> str:
|
||||||
|
"""Link a dependency name to its entry page; plain code span if unknown."""
|
||||||
|
fn = functions.get(name)
|
||||||
|
if not fn:
|
||||||
|
return f"`{name}`"
|
||||||
|
category = re.sub(r"^\d+-", "", fn["CATEGORY"][0])
|
||||||
|
return f"[`{name}`](/{SLUG_DIR}/{category}/{_entry_slug(name)}/)"
|
||||||
|
|
||||||
|
|
||||||
|
def _with_entries(body: str, path: Path, entries: dict) -> str:
|
||||||
|
"""Append this category's generated `## name` entries to its stub body."""
|
||||||
|
generated = entries.get(path.stem, [])
|
||||||
|
if not generated:
|
||||||
|
return body
|
||||||
|
blocks = [f"## {name}\n\n{entry}" for name, entry in generated]
|
||||||
|
return "\n\n".join(([body] if body.strip() else []) + blocks)
|
||||||
|
|
||||||
|
|
||||||
|
def _with_abbreviations(body: str, abbrs: dict[str, list[dict]]) -> str:
|
||||||
|
"""Inject generated abbreviation tables into the document placeholders."""
|
||||||
|
rendered_abbrs = {}
|
||||||
|
for cat, items in abbrs.items():
|
||||||
|
lines_cat = [" Abbreviation Description", " ───────────────────────────────────────────────────────────────────"]
|
||||||
|
for abbr in items:
|
||||||
|
name = abbr["name"]
|
||||||
|
desc = abbr["desc"]
|
||||||
|
|
||||||
|
# Left-pad description to ensure at least 2 spaces for cell split
|
||||||
|
name_part = name.ljust(16)
|
||||||
|
if len(name_part) < len(name) + 2:
|
||||||
|
name_part = name + " "
|
||||||
|
|
||||||
|
lines_cat.append(f" {name_part}{desc}")
|
||||||
|
rendered_abbrs[cat] = "\n".join(lines_cat)
|
||||||
|
|
||||||
|
for cat, table in rendered_abbrs.items():
|
||||||
|
placeholder = f"<!-- GENERATED: {cat} -->"
|
||||||
|
body = body.replace(placeholder, table)
|
||||||
|
|
||||||
|
return body
|
||||||
|
|
||||||
|
|
||||||
|
def build_concat(root: Path) -> str:
|
||||||
|
"""Concatenate the manual into one ordered markdown document.
|
||||||
|
|
||||||
|
Each file contributes `# {manTitle or title}` at a level matching its
|
||||||
|
depth, and its body headings are demoted by the same amount.
|
||||||
|
|
||||||
|
`root / "_pandoc.yml"` (if present) holds the original document's
|
||||||
|
pandoc metadata block (title/section/header/date/author) as raw text,
|
||||||
|
with no frontmatter fences and no Astro-visible frontmatter key. When
|
||||||
|
present, its contents are re-emitted byte-for-byte as the leading
|
||||||
|
`---`-fenced block, ahead of every heading.
|
||||||
|
"""
|
||||||
|
entries = build_entries(mt.parse_functions(FUNCTIONS))
|
||||||
|
chunks: list[str] = []
|
||||||
|
pandoc_path = root / "_pandoc.yml"
|
||||||
|
if pandoc_path.exists():
|
||||||
|
raw = pandoc_path.read_text().rstrip("\n")
|
||||||
|
chunks.append(f"---\n{raw}\n---")
|
||||||
|
for path, depth in mt.walk(root):
|
||||||
|
fm, body = mt.parse(path)
|
||||||
|
if not fm.get("man", True):
|
||||||
|
continue
|
||||||
|
heading = fm.get("manTitle") or fm.get("title", path.stem)
|
||||||
|
chunks.append("#" * (depth + 1) + " " + heading)
|
||||||
|
if _is_function_page(path, root):
|
||||||
|
body = _with_entries(body, path, entries)
|
||||||
|
elif "04-abbreviations" in path.parts:
|
||||||
|
abbrs = mt.parse_abbreviations(DOCS.parent / "conf.d")
|
||||||
|
body = _with_abbreviations(body, abbrs)
|
||||||
|
if body:
|
||||||
|
body = re.sub(r"<LinkButton.*?</LinkButton>\n*", "", body, flags=re.DOTALL)
|
||||||
|
body = re.sub(r"<CardGrid.*?</CardGrid>\n*", "", body, flags=re.DOTALL)
|
||||||
|
body = re.sub(r"\[([^\]]+)\]\(/[^)]+\)", r"\1", body)
|
||||||
|
chunks.append(mt.shift_headings(body, depth))
|
||||||
|
return "\n\n".join(chunks) + "\n"
|
||||||
|
|
||||||
|
|
||||||
|
SENTENCE_RE = re.compile(r"^(.+?[.!?])(\s|$)", re.S)
|
||||||
|
PIPELINE_KEYS = ("man", "site", "manTitle", "helpKeywords")
|
||||||
|
JSX_ATTR_ESCAPES = (
|
||||||
|
("&", "&"),
|
||||||
|
('"', """),
|
||||||
|
("<", "<"),
|
||||||
|
("{", "{"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _jsx_attr_escape(value: str) -> str:
|
||||||
|
"""Escape a string for safe use inside a quoted JSX attribute value.
|
||||||
|
|
||||||
|
`&` must go first so escaping later characters doesn't double-escape
|
||||||
|
the ampersands it introduces. `"` closes the attribute early; `<` and
|
||||||
|
`{` are otherwise-live MDX/JSX syntax that must not be interpreted.
|
||||||
|
"""
|
||||||
|
for char, escape in JSX_ATTR_ESCAPES:
|
||||||
|
value = value.replace(char, escape)
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def _first_sentence(body: str) -> str:
|
||||||
|
"""Extract a one-line description from the start of an entry body.
|
||||||
|
|
||||||
|
The `Synopsis:` block is skipped whole — label line plus its
|
||||||
|
deeper-indented continuation lines. It restates the calling convention,
|
||||||
|
which the card already shows as its title, so using one as the card
|
||||||
|
description wastes the line.
|
||||||
|
|
||||||
|
Source prose is hard-wrapped, so the leading paragraph is unwrapped
|
||||||
|
before the sentence match — otherwise a card truncates at the first
|
||||||
|
line break, mid-clause.
|
||||||
|
"""
|
||||||
|
para: list[str] = []
|
||||||
|
in_fence = False
|
||||||
|
syn_indent: int | None = None
|
||||||
|
for raw in body.split("\n"):
|
||||||
|
line = raw.strip()
|
||||||
|
indent = len(raw) - len(raw.lstrip())
|
||||||
|
if syn_indent is not None:
|
||||||
|
if line and indent <= syn_indent:
|
||||||
|
syn_indent = None
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
if line.startswith("```"):
|
||||||
|
in_fence = not in_fence
|
||||||
|
if para:
|
||||||
|
break
|
||||||
|
continue
|
||||||
|
if in_fence:
|
||||||
|
continue
|
||||||
|
if not line or line.startswith(("#", "|", "-", "*", ">")):
|
||||||
|
if para:
|
||||||
|
break
|
||||||
|
continue
|
||||||
|
if line.startswith("Synopsis:"):
|
||||||
|
syn_indent = indent
|
||||||
|
continue
|
||||||
|
para.append(line)
|
||||||
|
if not para:
|
||||||
|
return ""
|
||||||
|
text = " ".join(para)
|
||||||
|
m = SENTENCE_RE.match(text)
|
||||||
|
return (m.group(1) if m else text)[:160]
|
||||||
|
|
||||||
|
|
||||||
|
# Commands common enough in this manual that a block whose every line starts
|
||||||
|
# with one is certainly shell, not prose or a two-column reference table.
|
||||||
|
SHELL_HEADS = frozenset(
|
||||||
|
"""
|
||||||
|
abbr alias apt bg bind brew builtin cargo cat cd chmod code command cp curl
|
||||||
|
dnf docker echo end env exec export fg fish fisher for funcsave function git help
|
||||||
|
if jobs kitty ls man math mkdir mv nvim npm pacman paru pip pip3 pkg printf
|
||||||
|
python python3 rm set shutdown source string sudo switch systemctl test time
|
||||||
|
tmux touch trash type wget wezterm while yay zellij zypper
|
||||||
|
fish_default_key_bindings fish_vi_key_bindings
|
||||||
|
""".split()
|
||||||
|
)
|
||||||
|
|
||||||
|
SYNOPSIS_PREFIX = "Synopsis:"
|
||||||
|
EXAMPLE_PREFIX = "Example:"
|
||||||
|
INDENT = " "
|
||||||
|
|
||||||
|
|
||||||
|
def _is_prose(para: list[str]) -> bool:
|
||||||
|
"""True when a paragraph reads as sentences rather than as code or a table.
|
||||||
|
|
||||||
|
Column-aligned reference tables are the main thing to keep out of a
|
||||||
|
syntax-highlighted fence, and internal runs of two-or-more spaces are
|
||||||
|
what distinguishes them from prose. `<` and `{` are excluded because
|
||||||
|
the emitted paragraph is live markdown, where both would be parsed.
|
||||||
|
"""
|
||||||
|
text = " ".join(para)
|
||||||
|
if "<" in text or "{" in text:
|
||||||
|
return False
|
||||||
|
if not para or para[-1].rstrip()[-1:] not in ".:":
|
||||||
|
return False
|
||||||
|
return all(
|
||||||
|
len(line.split()) >= 3 and " " not in line.strip() for line in para
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _is_shell(para: list[str], entry_name: str | None) -> bool:
|
||||||
|
"""True when every line of a paragraph looks like a shell command."""
|
||||||
|
name_re = (
|
||||||
|
re.compile(rf"(?<![\w-]){re.escape(entry_name)}(?![\w-])")
|
||||||
|
if entry_name
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
for line in para:
|
||||||
|
stripped = line.strip()
|
||||||
|
if not stripped or stripped.startswith("#"):
|
||||||
|
continue
|
||||||
|
if name_re and name_re.search(stripped):
|
||||||
|
continue
|
||||||
|
if stripped.split()[0].lstrip("$").rstrip(";") not in SHELL_HEADS:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
# A lone indented line that's just a path ending in a known extension —
|
||||||
|
# e.g. pointing at where a file lives — reads better as a titled snippet
|
||||||
|
# than an unhighlighted grey slab.
|
||||||
|
PATH_LINE_RE = re.compile(r"^[~$][\w./{}-]*\.\w+$")
|
||||||
|
|
||||||
|
# A leading "# in local.fish" / "# local.fish" comment names the file an
|
||||||
|
# example belongs to; promote it to the fence title instead of leaving it
|
||||||
|
# as a literal comment inside the code.
|
||||||
|
FILENAME_COMMENT_RE = re.compile(r"^#\s*(?:in\s+)?([$~\w./-]+\.\w+)\s*$")
|
||||||
|
|
||||||
|
CELL_SPLIT = re.compile(r"\s{2,}")
|
||||||
|
|
||||||
|
# A rule line under a header row — the "Component Reference" tables'
|
||||||
|
# authoring convention (header, dashes, data rows all at the same indent,
|
||||||
|
# no ":"-terminated label). Either one solid run of dashes, or (RST-style)
|
||||||
|
# one dash run per column, gapped the same way CELL_SPLIT splits cells.
|
||||||
|
RULE_CELL_RE = re.compile(r"^[─\-]{3,}$")
|
||||||
|
|
||||||
|
|
||||||
|
def _cell(text: str, code: bool) -> str:
|
||||||
|
"""Render one table cell. `|` must be escaped even inside a code span."""
|
||||||
|
text = text.strip().replace("|", r"\|")
|
||||||
|
return f"`{text}`" if code and text else text
|
||||||
|
|
||||||
|
|
||||||
|
def _as_table(para: list[str]) -> str | None:
|
||||||
|
"""Render an aligned two-column block as a markdown table, else None.
|
||||||
|
|
||||||
|
Option and subcommand tables are the one thing in this manual that is
|
||||||
|
genuinely tabular, and the indented-code fallback renders them as a grey
|
||||||
|
slab. Everything else stays in that fallback: returning None is always
|
||||||
|
safe, so every check here is free to be conservative.
|
||||||
|
|
||||||
|
The rows must form one contiguous indented run, optionally introduced by
|
||||||
|
a label line (`Options:`) and closed by a sentence. Lines indented deeper
|
||||||
|
than the run are wrapped descriptions and fold into the row above.
|
||||||
|
"""
|
||||||
|
starts = [i for i, ln in enumerate(para) if ln.startswith(" ")]
|
||||||
|
if len(starts) < 2 or starts != list(range(starts[0], starts[-1] + 1)):
|
||||||
|
return None
|
||||||
|
head = para[: starts[0]]
|
||||||
|
body = para[starts[0] : starts[-1] + 1]
|
||||||
|
tail = para[starts[-1] + 1 :]
|
||||||
|
if head and not head[-1].rstrip().endswith(":"):
|
||||||
|
return None # a head that isn't a label means mixed content
|
||||||
|
|
||||||
|
indent = min(len(ln) - len(ln.lstrip()) for ln in body)
|
||||||
|
rows: list[list[str]] = []
|
||||||
|
for line in body:
|
||||||
|
if len(line) - len(line.lstrip()) > indent and rows:
|
||||||
|
rows[-1][1] += " " + line.strip()
|
||||||
|
continue
|
||||||
|
parts = CELL_SPLIT.split(line.strip(), 1)
|
||||||
|
if len(parts) != 2 or not parts[1].strip():
|
||||||
|
return None # not column-aligned; a numbered list, or prose
|
||||||
|
rows.append([parts[0], parts[1].strip()])
|
||||||
|
if len(rows) < 2:
|
||||||
|
return None
|
||||||
|
if any("<" in value or "{" in value for _, value in rows):
|
||||||
|
return None # live markdown in the prose column
|
||||||
|
|
||||||
|
out = [line.strip() for line in head]
|
||||||
|
out += ["| | |", "|---|---|"]
|
||||||
|
out += [f"| {_cell(k, True)} | {_cell(v, False)} |" for k, v in rows]
|
||||||
|
out += [line.strip() for line in tail]
|
||||||
|
return "\n".join(out)
|
||||||
|
|
||||||
|
|
||||||
|
def _as_ruled_table(para: list[str]) -> str | None:
|
||||||
|
"""Render a header + solid-rule + rows block as an N-column table, else None.
|
||||||
|
|
||||||
|
This is the "Component Reference" tables' convention: header row, a
|
||||||
|
dashed rule, then data rows at the same indent (no ":"-label, no extra
|
||||||
|
nesting — the two things _as_table looks for). A row that splits into
|
||||||
|
just one cell is a word-wrapped continuation of the row above; anything
|
||||||
|
else that doesn't match the header's column count is a source alignment
|
||||||
|
bug, so bail out to the code-block fallback rather than guess.
|
||||||
|
"""
|
||||||
|
if len(para) < 4:
|
||||||
|
return None
|
||||||
|
rule_cells = CELL_SPLIT.split(para[1].strip())
|
||||||
|
if not all(RULE_CELL_RE.match(cell) for cell in rule_cells):
|
||||||
|
return None
|
||||||
|
header = CELL_SPLIT.split(para[0].strip())
|
||||||
|
n = len(header)
|
||||||
|
if n < 2:
|
||||||
|
return None
|
||||||
|
rows: list[list[str]] = []
|
||||||
|
for line in para[2:]:
|
||||||
|
parts = CELL_SPLIT.split(line.strip(), n - 1)
|
||||||
|
if len(parts) == n:
|
||||||
|
rows.append(parts)
|
||||||
|
elif len(parts) == 1 and rows:
|
||||||
|
rows[-1][-1] += " " + parts[0].strip()
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
if len(rows) < 2:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Unlike _as_table's prose column, these tables legitimately contain
|
||||||
|
# placeholders like <session> or brace globs — code-span protects them
|
||||||
|
# instead of rejecting the whole table.
|
||||||
|
def cell(text: str, code: bool) -> str:
|
||||||
|
needs_protection = ("<" in text or "{" in text) and "`" not in text
|
||||||
|
return _cell(text, code or needs_protection)
|
||||||
|
|
||||||
|
out = [f"| {' | '.join(header)} |", "|" + "|".join(["---"] * n) + "|"]
|
||||||
|
for row in rows:
|
||||||
|
cells = [cell(row[0], True)] + [cell(c, False) for c in row[1:]]
|
||||||
|
out.append(f"| {' | '.join(cells)} |")
|
||||||
|
return "\n".join(out)
|
||||||
|
|
||||||
|
|
||||||
|
TREE_ROOT_RE = re.compile(r"^[~$][\w./{}-]*/$")
|
||||||
|
TREE_BRANCH_RE = re.compile(r"^([│ \t]*)[├└]──\s*(\S+)\s*(.*)$")
|
||||||
|
|
||||||
|
|
||||||
|
def _as_file_tree(para: list[str]) -> str | None:
|
||||||
|
"""Render a hand-drawn box-drawing tree as a Starlight <FileTree>, else None."""
|
||||||
|
if len(para) < 2 or not TREE_ROOT_RE.match(para[0].strip()):
|
||||||
|
return None
|
||||||
|
branches = []
|
||||||
|
for line in para[1:]:
|
||||||
|
m = TREE_BRANCH_RE.match(line)
|
||||||
|
if not m:
|
||||||
|
return None
|
||||||
|
branches.append(m.groups())
|
||||||
|
out = ["<FileTree>", f"- {para[0].strip()}"]
|
||||||
|
for prefix, name, desc in branches:
|
||||||
|
depth = len(prefix.replace('\t', ' ')) // 4
|
||||||
|
indent = " " * (depth + 1)
|
||||||
|
out.append(f"{indent}- {name} {desc}".rstrip())
|
||||||
|
out.append("</FileTree>")
|
||||||
|
return "\n".join(out)
|
||||||
|
|
||||||
|
|
||||||
|
def _render_para(para: list[str], entry_name: str | None, deeper: bool) -> str:
|
||||||
|
"""Render one paragraph of a former indented block.
|
||||||
|
|
||||||
|
`deeper` marks paragraphs carrying their own extra indentation — nested
|
||||||
|
option tables, whose alignment only survives inside a code block.
|
||||||
|
"""
|
||||||
|
if not deeper:
|
||||||
|
if _is_prose(para):
|
||||||
|
return "\n".join(line.strip() for line in para)
|
||||||
|
if len(para) == 1 and PATH_LINE_RE.match(para[0].strip()):
|
||||||
|
path = para[0].strip()
|
||||||
|
name = path.rsplit("/", 1)[-1]
|
||||||
|
return f'```fish title="{name}"\n{path}\n```'
|
||||||
|
if _is_shell(para, entry_name):
|
||||||
|
body = para
|
||||||
|
title = None
|
||||||
|
m = FILENAME_COMMENT_RE.match(para[0].strip())
|
||||||
|
if m:
|
||||||
|
title, body = m.group(1), para[1:]
|
||||||
|
info = f'fish title="{title}"' if title else "fish"
|
||||||
|
return f"```{info}\n" + "\n".join(body) + "\n```"
|
||||||
|
table = _as_ruled_table(para) or _as_table(para) or _as_file_tree(para)
|
||||||
|
if table is not None:
|
||||||
|
return table
|
||||||
|
return "\n".join(INDENT + line for line in para)
|
||||||
|
|
||||||
|
|
||||||
|
def _prettify_block(block: list[str], entry_name: str | None) -> str:
|
||||||
|
"""Convert one indented block into fenced code, prose, and tables.
|
||||||
|
|
||||||
|
The manual is authored man-page style: every example, table, and
|
||||||
|
description sits in a single 4-space-indented block, which renders on
|
||||||
|
the site as one unhighlighted grey slab. Splitting a block into its
|
||||||
|
paragraphs recovers the structure the indentation flattened.
|
||||||
|
"""
|
||||||
|
lines = [line[len(INDENT) :] if line.startswith(INDENT) else line for line in block]
|
||||||
|
|
||||||
|
out: list[str] = []
|
||||||
|
if lines and lines[0].startswith(SYNOPSIS_PREFIX):
|
||||||
|
synopsis = [lines.pop(0)[len(SYNOPSIS_PREFIX) :].strip()]
|
||||||
|
# A multi-line synopsis is authored aligned under the first line;
|
||||||
|
# keep the whole thing in one fence rather than orphaning the rest.
|
||||||
|
while lines and lines[0].startswith(" "):
|
||||||
|
synopsis.append(lines.pop(0).strip())
|
||||||
|
# A "Usage" title (Starlight's filename-title convention, repurposed
|
||||||
|
# as a label) makes the synopsis read as a snippet of the function
|
||||||
|
# it documents rather than a bare command example.
|
||||||
|
info = 'fish title="Usage"' if entry_name else "fish"
|
||||||
|
out.append(f"```{info}\n" + "\n".join(synopsis) + "\n```")
|
||||||
|
|
||||||
|
para: list[str] = []
|
||||||
|
for line in lines + [""]:
|
||||||
|
if line.strip():
|
||||||
|
para.append(line)
|
||||||
|
continue
|
||||||
|
if para:
|
||||||
|
if para[0].strip() == EXAMPLE_PREFIX:
|
||||||
|
example = para[1:]
|
||||||
|
if example and _is_shell(example, entry_name):
|
||||||
|
body = "\n".join(example)
|
||||||
|
out.append(f'```fish title="Examples"\n{body}\n```')
|
||||||
|
else:
|
||||||
|
deeper = any(line.startswith(" ") for line in example)
|
||||||
|
out.append(_render_para(example, entry_name, deeper))
|
||||||
|
else:
|
||||||
|
deeper = any(line.startswith(" ") for line in para)
|
||||||
|
out.append(_render_para(para, entry_name, deeper))
|
||||||
|
para = []
|
||||||
|
return "\n\n".join(chunk for chunk in out if chunk.strip())
|
||||||
|
|
||||||
|
|
||||||
|
ASIDE_LABELS: dict[str, tuple[str, str, str | None]] = {
|
||||||
|
"NOTE": ("note", "Note", None),
|
||||||
|
"IMPORTANT": ("note", "Important", "star"),
|
||||||
|
"TIP": ("tip", "Tip", None),
|
||||||
|
"HINT": ("tip", "Hint", "question-circle"),
|
||||||
|
"WARNING": ("caution", "Warning", "warning"),
|
||||||
|
"CAUTION": ("caution", "Caution", None),
|
||||||
|
"DANGER": ("danger", "Danger", None),
|
||||||
|
}
|
||||||
|
ASIDE_RE = re.compile(rf"^({'|'.join(ASIDE_LABELS)}):\s*(.*)$")
|
||||||
|
|
||||||
|
|
||||||
|
def _as_aside(para: list[str]) -> str | None:
|
||||||
|
"""Render a `LABEL: ...` flat paragraph as a Starlight <Aside>, else None."""
|
||||||
|
m = ASIDE_RE.match(para[0])
|
||||||
|
if not m:
|
||||||
|
return None
|
||||||
|
label, rest = m.groups()
|
||||||
|
aside_type, title, icon = ASIDE_LABELS[label]
|
||||||
|
body = "\n".join(([rest] if rest else []) + para[1:])
|
||||||
|
attrs = f'type="{aside_type}" title="{title}"'
|
||||||
|
if icon:
|
||||||
|
attrs += f' icon="{icon}"'
|
||||||
|
return f"<Aside {attrs}>\n{body}\n</Aside>"
|
||||||
|
|
||||||
|
|
||||||
|
def prettify(body: str, entry_name: str | None = None) -> str:
|
||||||
|
"""Rewrite a body's indented code blocks and labeled asides for the website.
|
||||||
|
|
||||||
|
Site-only: the man page and `config-help` keep reading the untouched
|
||||||
|
SSOT, where the indented form and the `LABEL:` text are exactly what
|
||||||
|
pandoc/`config-help` want.
|
||||||
|
"""
|
||||||
|
out: list[str] = []
|
||||||
|
block: list[str] = []
|
||||||
|
flat: list[str] = []
|
||||||
|
in_fence = False
|
||||||
|
|
||||||
|
def flush_flat() -> None:
|
||||||
|
out.append(_as_aside(flat) or "\n".join(flat))
|
||||||
|
|
||||||
|
for line in body.split("\n"):
|
||||||
|
if mt.FENCE_RE.match(line):
|
||||||
|
in_fence = not in_fence
|
||||||
|
if not in_fence and (line.startswith(INDENT) or (not line.strip() and block)):
|
||||||
|
if flat:
|
||||||
|
flush_flat()
|
||||||
|
flat.clear()
|
||||||
|
block.append(line)
|
||||||
|
continue
|
||||||
|
if block:
|
||||||
|
while block and not block[-1].strip():
|
||||||
|
block.pop()
|
||||||
|
out.append(_prettify_block(block, entry_name))
|
||||||
|
out.append("")
|
||||||
|
block = []
|
||||||
|
if in_fence or not line.strip():
|
||||||
|
if flat:
|
||||||
|
flush_flat()
|
||||||
|
flat.clear()
|
||||||
|
out.append(line)
|
||||||
|
else:
|
||||||
|
flat.append(line)
|
||||||
|
|
||||||
|
if flat:
|
||||||
|
flush_flat()
|
||||||
|
if block:
|
||||||
|
while block and not block[-1].strip():
|
||||||
|
block.pop()
|
||||||
|
out.append(_prettify_block(block, entry_name))
|
||||||
|
return "\n".join(out)
|
||||||
|
|
||||||
|
|
||||||
|
ENTRY_HEADS = {
|
||||||
|
"ARGUMENTS": "Arguments:",
|
||||||
|
"EXIT STATUS": "Exit Status:",
|
||||||
|
"RETURNS": "Returns:",
|
||||||
|
"NOTES": "Notes:",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def render_entry(fn: dict[str, list[str]], used_by: list[str], link=None) -> str:
|
||||||
|
"""Render one parsed function header as a manual entry body.
|
||||||
|
|
||||||
|
Emits the same man-page shape Section 5 was authored in — one 4-space
|
||||||
|
indented block opening with `Synopsis:` — so `prettify` keeps handling it
|
||||||
|
for the site and pandoc keeps handling it for the man page, with no
|
||||||
|
special case on either side.
|
||||||
|
|
||||||
|
`link` maps a function name to its markdown link, or is None for the man
|
||||||
|
page, where a URL in the middle of a sentence is noise.
|
||||||
|
"""
|
||||||
|
out: list[str] = []
|
||||||
|
syn = fn.get("SYNOPSIS", [])
|
||||||
|
if syn:
|
||||||
|
pad = " " * len(SYNOPSIS_PREFIX + " ")
|
||||||
|
out.append(f"{SYNOPSIS_PREFIX} {syn[0]}")
|
||||||
|
out += [pad + line for line in syn[1:]]
|
||||||
|
out.append("")
|
||||||
|
for line in fn.get("DESCRIPTION", []):
|
||||||
|
out.append(line)
|
||||||
|
for label, head in ENTRY_HEADS.items():
|
||||||
|
body = fn.get(label)
|
||||||
|
if not body:
|
||||||
|
continue
|
||||||
|
out += ["", head] + [" " + line for line in body]
|
||||||
|
if fn.get("EXAMPLE"):
|
||||||
|
out += ["", EXAMPLE_PREFIX] + fn["EXAMPLE"]
|
||||||
|
|
||||||
|
block = "\n".join((INDENT + line).rstrip() for line in out)
|
||||||
|
|
||||||
|
def names(raw: list[str]) -> list[str]:
|
||||||
|
return [n for n in re.split(r"[,\s]+", " ".join(raw)) if n]
|
||||||
|
|
||||||
|
refs = []
|
||||||
|
for label, values in (
|
||||||
|
("Dependencies", names(fn.get("DEPENDENCIES", []))),
|
||||||
|
("Used by", sorted(used_by)),
|
||||||
|
):
|
||||||
|
if values:
|
||||||
|
rendered = ", ".join(link(v) if link else f"`{v}`" for v in values)
|
||||||
|
refs.append(f"**{label}:** {rendered}")
|
||||||
|
if refs:
|
||||||
|
block += "\n\n" + "\n\n".join(refs)
|
||||||
|
return block
|
||||||
|
|
||||||
|
|
||||||
|
def build_entries(functions: dict[str, dict], link=None) -> dict[str, list[tuple[str, str]]]:
|
||||||
|
"""Group rendered entries by category stem, ordered by function name.
|
||||||
|
|
||||||
|
The `Used by` reverse index is computed here in one pass rather than
|
||||||
|
authored: a bidirectional link maintained by hand drifts the moment one
|
||||||
|
side is edited.
|
||||||
|
"""
|
||||||
|
used_by: dict[str, list[str]] = {}
|
||||||
|
for name, fn in functions.items():
|
||||||
|
for dep in re.split(r"[,\s]+", " ".join(fn.get("DEPENDENCIES", []))):
|
||||||
|
if dep in functions:
|
||||||
|
used_by.setdefault(dep, []).append(name)
|
||||||
|
|
||||||
|
out: dict[str, list[tuple[str, str]]] = {}
|
||||||
|
for name in sorted(functions):
|
||||||
|
fn = functions[name]
|
||||||
|
body = render_entry(fn, used_by.get(name, []), link)
|
||||||
|
out.setdefault(fn["CATEGORY"][0], []).append((name, body))
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def _page_fm(fm: dict) -> dict:
|
||||||
|
"""Strip pipeline-only keys from frontmatter destined for the site."""
|
||||||
|
return {k: v for k, v in fm.items() if k not in PIPELINE_KEYS}
|
||||||
|
|
||||||
|
|
||||||
|
def _split_entries(body: str) -> tuple[str, list[tuple[str, str]]]:
|
||||||
|
"""Split a category body into (intro, [(entry title, entry body)]).
|
||||||
|
|
||||||
|
Fence-aware: an H2-looking line (`## ...`) inside a fenced code block
|
||||||
|
(tracked the same way as `manualtools.shift_headings`) is treated as
|
||||||
|
ordinary body text, not an entry boundary.
|
||||||
|
"""
|
||||||
|
lines = body.split("\n")
|
||||||
|
heading_re = re.compile(r"^## (.+)$")
|
||||||
|
boundaries: list[tuple[int, str]] = []
|
||||||
|
in_fence = False
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
if mt.FENCE_RE.match(line):
|
||||||
|
in_fence = not in_fence
|
||||||
|
continue
|
||||||
|
if not in_fence:
|
||||||
|
m = heading_re.match(line)
|
||||||
|
if m:
|
||||||
|
boundaries.append((i, m.group(1)))
|
||||||
|
|
||||||
|
if not boundaries:
|
||||||
|
return body.strip(), []
|
||||||
|
|
||||||
|
intro = "\n".join(lines[: boundaries[0][0]]).strip()
|
||||||
|
entries = []
|
||||||
|
for idx, (line_no, title) in enumerate(boundaries):
|
||||||
|
start = line_no + 1
|
||||||
|
end = boundaries[idx + 1][0] if idx + 1 < len(boundaries) else len(lines)
|
||||||
|
# Strip newlines only: a bare .strip() would eat the leading
|
||||||
|
# indentation of the entry's first line, detaching the `Synopsis:`
|
||||||
|
# line from the indented block it opens.
|
||||||
|
entry_body = "\n".join(lines[start:end]).strip("\n")
|
||||||
|
entries.append((title.strip(), entry_body))
|
||||||
|
return intro, entries
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def _inject_subheading_cards(body: str) -> str:
|
||||||
|
"""Extract `## Heading`s and inject a CardGrid after the intro."""
|
||||||
|
headings = []
|
||||||
|
for line in body.splitlines():
|
||||||
|
m = re.match(r"^##\s+(.+)$", line)
|
||||||
|
if m:
|
||||||
|
headings.append(m.group(1).strip())
|
||||||
|
|
||||||
|
if len(headings) < 2:
|
||||||
|
return body
|
||||||
|
|
||||||
|
parts = body.split("\n## ", 1)
|
||||||
|
if len(parts) != 2:
|
||||||
|
return body
|
||||||
|
|
||||||
|
intro = parts[0].strip()
|
||||||
|
rest = "## " + parts[1]
|
||||||
|
|
||||||
|
cards = []
|
||||||
|
for title in headings:
|
||||||
|
safe_title = _jsx_attr_escape(title)
|
||||||
|
slug = re.sub(r"[^\w\s-]", "", title.lower())
|
||||||
|
slug = re.sub(r"[-\s]+", "-", slug).strip("-")
|
||||||
|
cards.append(f' <LinkCard title="{safe_title}" href="#{slug}" />')
|
||||||
|
|
||||||
|
cardgrid = "<CardGrid>\n" + "\n".join(cards) + "\n</CardGrid>\n\n"
|
||||||
|
|
||||||
|
return f"{intro}\n\n{cardgrid}{rest}"
|
||||||
|
|
||||||
|
ASTRO_ASIDE_COMPONENTS = {"<Aside": "Aside", "<FileTree": "FileTree", "<LinkButton": "LinkButton", "<CardGrid": "CardGrid", "<LinkCard": "LinkCard"}
|
||||||
|
|
||||||
|
|
||||||
|
def _write_prettified(target: Path, fm: dict, content: str) -> None:
|
||||||
|
"""Write a prettified page, promoting to .mdx when it needs a component import.
|
||||||
|
|
||||||
|
A page stays .md (prettify()'s default, no imports) unless its rendered
|
||||||
|
content actually contains an <Aside> or <FileTree> — the only two
|
||||||
|
components a prettified (non-hand-built) page can contain.
|
||||||
|
"""
|
||||||
|
needed = [name for marker, name in ASTRO_ASIDE_COMPONENTS.items() if marker in content]
|
||||||
|
if needed:
|
||||||
|
imports = f"import {{ {', '.join(needed)} }} from '@astrojs/starlight/components';\n\n"
|
||||||
|
target = target.with_suffix(".mdx")
|
||||||
|
content = imports + content
|
||||||
|
target.write_text(mt.serialize(fm, content))
|
||||||
|
|
||||||
|
|
||||||
|
def build_site(root: Path, out: Path) -> list[dict]:
|
||||||
|
"""Write the Starlight content tree. Returns the sidebar structure."""
|
||||||
|
if out.exists():
|
||||||
|
shutil.rmtree(out)
|
||||||
|
out.mkdir(parents=True)
|
||||||
|
|
||||||
|
functions = mt.parse_functions(FUNCTIONS)
|
||||||
|
entries = build_entries(functions, link=lambda n: _entry_link(n, functions))
|
||||||
|
|
||||||
|
sidebar: list[dict] = [{"label": "Home", "link": "/"}]
|
||||||
|
standard_groups: dict = {}
|
||||||
|
functions_group: dict = {}
|
||||||
|
functions_index_target = None
|
||||||
|
functions_index_fm = None
|
||||||
|
functions_index_body = None
|
||||||
|
functions_cards = []
|
||||||
|
for path, _depth in mt.walk(root):
|
||||||
|
fm, body = mt.parse(path)
|
||||||
|
if not fm.get("site", True):
|
||||||
|
continue
|
||||||
|
|
||||||
|
rel = path.relative_to(root)
|
||||||
|
is_function_dir = rel.parts and rel.parts[0].endswith("-functions")
|
||||||
|
|
||||||
|
if not is_function_dir:
|
||||||
|
target = out / rel
|
||||||
|
if "04-abbreviations" in path.parts:
|
||||||
|
abbrs = mt.parse_abbreviations(DOCS.parent / "conf.d")
|
||||||
|
body = _with_abbreviations(body, abbrs)
|
||||||
|
target.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
body = _inject_subheading_cards(body)
|
||||||
|
_write_prettified(target, _page_fm(fm), prettify(body))
|
||||||
|
|
||||||
|
if len(rel.parts) > 1:
|
||||||
|
group_dir = rel.parts[0]
|
||||||
|
if rel.name == "index.md":
|
||||||
|
group = {
|
||||||
|
"label": fm["title"],
|
||||||
|
"collapsed": True,
|
||||||
|
"items": [{"label": "Categories", "link": f"/{group_dir}/"}]
|
||||||
|
}
|
||||||
|
standard_groups[group_dir] = group
|
||||||
|
sidebar.append(group)
|
||||||
|
elif rel.name != "404.md":
|
||||||
|
if group_dir in standard_groups:
|
||||||
|
standard_groups[group_dir]["items"].append({
|
||||||
|
"label": fm["title"],
|
||||||
|
"link": f"/{group_dir}/{rel.stem}/"
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
sidebar.append({"label": fm["title"], "link": f"/{group_dir}/{rel.stem}/"})
|
||||||
|
else:
|
||||||
|
if rel.name not in ("index.md", "404.md"):
|
||||||
|
sidebar.append({"label": fm["title"], "link": "/" + rel.stem + "/"})
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Section 5: category index page keeps its slot; entries explode.
|
||||||
|
#
|
||||||
|
# Deliberately NOT "functions": Cloudflare Pages reserves a top-level
|
||||||
|
# `functions/` directory in the deploy output for Pages Functions
|
||||||
|
# (server-side handlers) and silently drops it from the static-asset
|
||||||
|
# upload. The pages build fine and never arrive — every entry 404s in
|
||||||
|
# production while working locally. test_site_avoids_reserved_dir
|
||||||
|
# guards this.
|
||||||
|
slug_dir = SLUG_DIR
|
||||||
|
if rel.name == "index.md":
|
||||||
|
functions_index_target = out / slug_dir / "index.md"
|
||||||
|
functions_index_fm = fm
|
||||||
|
functions_index_body = body
|
||||||
|
functions_cards = []
|
||||||
|
|
||||||
|
# Built explicitly rather than by `autogenerate`, which labels
|
||||||
|
# each group with its raw directory slug and republishes this
|
||||||
|
# index as a child of the group it already titles.
|
||||||
|
functions_group = {
|
||||||
|
"label": fm["title"],
|
||||||
|
"collapsed": True,
|
||||||
|
"items": [{"label": "Categories", "link": f"/{slug_dir}/"}],
|
||||||
|
}
|
||||||
|
sidebar.append(functions_group)
|
||||||
|
continue
|
||||||
|
|
||||||
|
category = re.sub(r"^\d+-", "", rel.stem)
|
||||||
|
cat_dir = out / slug_dir / category
|
||||||
|
cat_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
intro, page_entries = _split_entries(_with_entries(body, path, entries))
|
||||||
|
|
||||||
|
cat_title = fm["title"]
|
||||||
|
cat_desc = fm.get("description", "")
|
||||||
|
safe_title = _jsx_attr_escape(cat_title)
|
||||||
|
safe_desc = _jsx_attr_escape(cat_desc)
|
||||||
|
href = f"/{slug_dir}/{category}/"
|
||||||
|
functions_cards.append(
|
||||||
|
f' <LinkCard title="{safe_title}" href="{href}"'
|
||||||
|
+ (f' description="{safe_desc}"' if cat_desc else "")
|
||||||
|
+ " />"
|
||||||
|
)
|
||||||
|
|
||||||
|
cards = []
|
||||||
|
links = []
|
||||||
|
for title, entry_body in page_entries:
|
||||||
|
entry_slug = _entry_slug(title)
|
||||||
|
desc = _first_sentence(entry_body)
|
||||||
|
entry_fm = {"title": title}
|
||||||
|
if desc:
|
||||||
|
entry_fm["description"] = desc
|
||||||
|
_write_prettified(
|
||||||
|
cat_dir / f"{entry_slug}.md",
|
||||||
|
entry_fm,
|
||||||
|
prettify(entry_body, title.split()[0]),
|
||||||
|
)
|
||||||
|
href = f"/{slug_dir}/{category}/{entry_slug}/"
|
||||||
|
links.append({"label": title, "link": href})
|
||||||
|
safe_title = _jsx_attr_escape(title)
|
||||||
|
safe_desc = _jsx_attr_escape(desc)
|
||||||
|
cards.append(
|
||||||
|
f' <LinkCard title="{safe_title}" href="{href}"'
|
||||||
|
+ (f' description="{safe_desc}"' if desc else "")
|
||||||
|
+ " />"
|
||||||
|
)
|
||||||
|
|
||||||
|
overview = (
|
||||||
|
"import { CardGrid, LinkCard } from '@astrojs/starlight/components';\n\n"
|
||||||
|
+ (f"{intro}\n\n" if intro else "")
|
||||||
|
+ "<CardGrid>\n"
|
||||||
|
+ "\n".join(cards)
|
||||||
|
+ "\n</CardGrid>\n"
|
||||||
|
)
|
||||||
|
(cat_dir / "index.mdx").write_text(mt.serialize(_page_fm(fm), overview))
|
||||||
|
|
||||||
|
functions_group.setdefault("items", []).append(
|
||||||
|
{
|
||||||
|
"label": fm["title"],
|
||||||
|
"collapsed": True,
|
||||||
|
"items": [
|
||||||
|
{"label": f"{fm['title']} Overview", "link": f"/{slug_dir}/{category}/"},
|
||||||
|
*links,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if functions_index_target:
|
||||||
|
overview_content = (
|
||||||
|
(f"{functions_index_body}\n\n" if functions_index_body.strip() else "")
|
||||||
|
+ "<CardGrid>\n"
|
||||||
|
+ "\n".join(functions_cards)
|
||||||
|
+ "\n</CardGrid>\n"
|
||||||
|
)
|
||||||
|
_write_prettified(functions_index_target, _page_fm(functions_index_fm), prettify(overview_content))
|
||||||
|
|
||||||
|
return sidebar
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
ap = argparse.ArgumentParser(description=__doc__)
|
||||||
|
ap.add_argument("--concat", action="store_true", help="emit the pandoc document")
|
||||||
|
ap.add_argument("--site", action="store_true", help="emit the Starlight content tree")
|
||||||
|
ap.add_argument("-o", "--output", type=Path, help="write to PATH instead of stdout")
|
||||||
|
args = ap.parse_args()
|
||||||
|
|
||||||
|
if not (args.concat or args.site):
|
||||||
|
ap.error("nothing to do: pass --concat and/or --site")
|
||||||
|
|
||||||
|
if args.site:
|
||||||
|
src = DOCS / "site" / "src"
|
||||||
|
out = src / "content" / "docs"
|
||||||
|
sidebar = build_site(MANUAL, out)
|
||||||
|
(src / "sidebar.json").write_text(json.dumps(sidebar, indent=2) + "\n")
|
||||||
|
print(f"wrote site content to {out} ({len(sidebar)} sidebar entries)")
|
||||||
|
|
||||||
|
if args.concat:
|
||||||
|
text = build_concat(MANUAL)
|
||||||
|
if args.output:
|
||||||
|
args.output.write_text(text)
|
||||||
|
print(f"wrote {args.output}")
|
||||||
|
else:
|
||||||
|
sys.stdout.write(text)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent))
|
||||||
|
raise SystemExit(main())
|
||||||
+4871
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,326 @@
|
|||||||
|
# Fish Config Help Index
|
||||||
|
# Format: keyword=exact heading text as it appears in fish-config.md
|
||||||
|
# Multiple keywords may map to the same heading.
|
||||||
|
# Update this file whenever headings are added, removed, or renamed.
|
||||||
|
# config-help uses this for fast exact lookups; unknown keywords fall back
|
||||||
|
# to a normalized heading scan automatically.
|
||||||
|
|
||||||
|
# ── Top-level ─────────────────────────────────────────────────
|
||||||
|
name=# NAME
|
||||||
|
synopsis=# SYNOPSIS
|
||||||
|
description=# DESCRIPTION
|
||||||
|
toc=# TABLE OF CONTENTS
|
||||||
|
contents=# TABLE OF CONTENTS
|
||||||
|
autopair=# DESCRIPTION
|
||||||
|
puffer=# DESCRIPTION
|
||||||
|
puffer-fish=# DESCRIPTION
|
||||||
|
logging-events=# DESCRIPTION
|
||||||
|
|
||||||
|
# ── Section 1: Configuration Variables ───────────────────────
|
||||||
|
variables=# 1. CONFIGURATION VARIABLES
|
||||||
|
config=# 1. CONFIGURATION VARIABLES
|
||||||
|
xdg=## Environment Directories (XDG)
|
||||||
|
toolhomes=## Tool Homes (XDG-compliant)
|
||||||
|
editor=## Editor and Pager
|
||||||
|
pager=## Editor and Pager
|
||||||
|
scrollback=## Scrollback History
|
||||||
|
__fish_scrollback_history_dir=## Scrollback History
|
||||||
|
__fish_scrollback_history_max_files=## Scrollback History
|
||||||
|
scrollback-dir=## Scrollback History
|
||||||
|
|
||||||
|
# ── Section 2: PATH ───────────────────────────────────────────
|
||||||
|
path=# 2. PATH SETUP
|
||||||
|
|
||||||
|
# ── Section 3: Key Bindings ───────────────────────────────────
|
||||||
|
keybindings=# 3. KEY BINDINGS
|
||||||
|
bindings=# 3. KEY BINDINGS
|
||||||
|
key-bindings=# 3. KEY BINDINGS
|
||||||
|
keys=# 3. KEY BINDINGS
|
||||||
|
fzf-bindings=## FZF Bindings (bundled from PatrickF1/fzf.fish)
|
||||||
|
fzf=## FZF Bindings (bundled from PatrickF1/fzf.fish)
|
||||||
|
|
||||||
|
# ── Section 4: Abbreviations ──────────────────────────────────
|
||||||
|
abbreviations=# 4. ABBREVIATIONS
|
||||||
|
abbr=# 4. ABBREVIATIONS
|
||||||
|
abbrs=# 4. ABBREVIATIONS
|
||||||
|
editors-abbr=## 4.1 Editors
|
||||||
|
nav=## 4.2 Navigation and Listing
|
||||||
|
navigation=## 4.2 Navigation and Listing
|
||||||
|
listing=## 4.2 Navigation and Listing
|
||||||
|
git-abbr=## 4.3 Git
|
||||||
|
terminal=## 4.4 Terminal Windows, Tabs, and Panes
|
||||||
|
panes=## 4.4 Terminal Windows, Tabs, and Panes
|
||||||
|
windows=## 4.4 Terminal Windows, Tabs, and Panes
|
||||||
|
tabs=## 4.4 Terminal Windows, Tabs, and Panes
|
||||||
|
chezmoi=## 4.5 Chezmoi
|
||||||
|
docker=## 4.6 Docker
|
||||||
|
systemctl=## 4.7 Systemctl
|
||||||
|
systemd=## 4.7 Systemctl
|
||||||
|
ai-abbr=## 4.8 AI Assistants
|
||||||
|
history=## 4.9 History Expansion
|
||||||
|
misc-abbr=## 4.10 Miscellaneous
|
||||||
|
|
||||||
|
# ── Section 5: Functions ──────────────────────────────────────
|
||||||
|
functions=# 5. FUNCTIONS REFERENCE
|
||||||
|
files=## 5.1 File and Directory
|
||||||
|
cat=### cat
|
||||||
|
copy=### copy
|
||||||
|
du=### du
|
||||||
|
dusize=### dusize
|
||||||
|
ls=### ls
|
||||||
|
lsr=### lsr
|
||||||
|
lss=### lss
|
||||||
|
lstree=### lstree
|
||||||
|
lt=### lt
|
||||||
|
ltr=### ltr
|
||||||
|
lx=### lx
|
||||||
|
mkdir=### mkdir
|
||||||
|
mkcd=### mkcd
|
||||||
|
poke=### poke
|
||||||
|
rm=### rm
|
||||||
|
rg=### rg
|
||||||
|
scrub=### scrub
|
||||||
|
nav-fns=## 5.2 Navigation
|
||||||
|
cdi=### cdi
|
||||||
|
clone=### clone
|
||||||
|
clonet=### clonet
|
||||||
|
editors=## 5.3 Editors and Viewers
|
||||||
|
edit=### edit
|
||||||
|
fc=### fc
|
||||||
|
less=### less
|
||||||
|
rawfish=### rawfish
|
||||||
|
view=### view
|
||||||
|
git=## 5.4 Git and Version Control
|
||||||
|
auto-pull=### auto-pull
|
||||||
|
branch=### branch
|
||||||
|
gi=### gi
|
||||||
|
gitignore=### gi
|
||||||
|
git-clean=### git-clean
|
||||||
|
gitup=### gitup
|
||||||
|
gitui=### gitui
|
||||||
|
hist=### hist
|
||||||
|
pkg=### pkg
|
||||||
|
package=### pkg
|
||||||
|
package-manager=## 5.5 Package Management
|
||||||
|
packages=## 5.5 Package Management
|
||||||
|
search=### search
|
||||||
|
upgrade=### upgrade
|
||||||
|
cleanup=### cleanup
|
||||||
|
parur=### parur
|
||||||
|
deps=## 5.6 Dependency Management
|
||||||
|
fish-deps=### fish-deps
|
||||||
|
check-deps=### check_fish_deps
|
||||||
|
system=## 5.7 System and Monitoring
|
||||||
|
top=### top
|
||||||
|
swapstat=### swapstat
|
||||||
|
sbver=### sbver
|
||||||
|
ports=### ports
|
||||||
|
screensleep=### screensleep
|
||||||
|
lock=### lock
|
||||||
|
sudo-toggle=### sudo-toggle
|
||||||
|
limine=### limine-edit
|
||||||
|
terminal-mgmt=## 5.8 Terminal Management
|
||||||
|
tab=### tab
|
||||||
|
split=### split
|
||||||
|
spwin=### spwin
|
||||||
|
detach=### detach
|
||||||
|
bkg=### bkg
|
||||||
|
jobrunner=### jobrunner
|
||||||
|
jr=### jr
|
||||||
|
ssh=### ssh
|
||||||
|
clipboard=## 5.9 Clipboard
|
||||||
|
copy-fn=### y
|
||||||
|
paste=### paste
|
||||||
|
network=## 5.10 Network
|
||||||
|
gip=### gip
|
||||||
|
ping=### ping
|
||||||
|
qr=### qr
|
||||||
|
logging=## 5.11 Pager and Logging
|
||||||
|
logs=### logs
|
||||||
|
smart-exit=### smart_exit
|
||||||
|
ai=## 5.12 AI and Developer Tools
|
||||||
|
antigravity-ide=### antigravity-ide
|
||||||
|
agy=### agy
|
||||||
|
agents-init=### agents-init
|
||||||
|
agents=### agents-init
|
||||||
|
agents-tools=### agents-init
|
||||||
|
version-bump=### agents-init
|
||||||
|
.version=### agents-init
|
||||||
|
structure-version=### agents-init
|
||||||
|
core.hooksPath=### agents-init
|
||||||
|
devlogs=### agents-init
|
||||||
|
claude-cli=### claude
|
||||||
|
claude-docs=### claude-docs
|
||||||
|
claude-pr=### claude-pr
|
||||||
|
qc=### qc
|
||||||
|
quick-chat=### qc
|
||||||
|
aichat=### qc
|
||||||
|
superpowers=### superpowers
|
||||||
|
media=## 5.13 Media and Utilities
|
||||||
|
dng2avif=### dng2avif
|
||||||
|
spark=### spark
|
||||||
|
yt-dlp=### yt-dlp
|
||||||
|
miscfns=## 5.14 Miscellaneous
|
||||||
|
config-help=### config-help
|
||||||
|
open-url=### open-url
|
||||||
|
url-open=### open-url
|
||||||
|
repo-open=### repo-open
|
||||||
|
open-repo=### repo-open
|
||||||
|
config-update=### config-update
|
||||||
|
config-settings=### config-settings
|
||||||
|
config-toggle=### config-settings
|
||||||
|
toggle=### config-settings
|
||||||
|
bash=### bash
|
||||||
|
cheat=### cheat
|
||||||
|
dockup=### dockup
|
||||||
|
joplin=### joplin
|
||||||
|
replay=### replay
|
||||||
|
tmux=### tmux-clean
|
||||||
|
wake-lock=### wake-lock
|
||||||
|
|
||||||
|
# ── Tool-name synonyms (replacement → shadowed command) ──────
|
||||||
|
# These tools don't appear in any heading, so the fallback scan can't
|
||||||
|
# find them; map each to the function that wraps it.
|
||||||
|
eza=### ls
|
||||||
|
exa=### ls
|
||||||
|
lsd=### ls
|
||||||
|
trash=### rm
|
||||||
|
btop=### top
|
||||||
|
prettyping=### ping
|
||||||
|
duf=### du
|
||||||
|
dust=### du
|
||||||
|
kitten=### ssh
|
||||||
|
bat=### cat
|
||||||
|
|
||||||
|
# ── Tool integrations (Section: Integrations) ────────────────
|
||||||
|
zoxide=### Zoxide
|
||||||
|
z=### Zoxide
|
||||||
|
direnv=### DirEnv
|
||||||
|
venv=### Auto Python Venv
|
||||||
|
virtualenv=### Auto Python Venv
|
||||||
|
python=### Auto Python Venv
|
||||||
|
wakatime=### WakaTime
|
||||||
|
tailscale=### Tailscale
|
||||||
|
done=### Done Notifications
|
||||||
|
notifications=### Done Notifications
|
||||||
|
notify=### Done Notifications
|
||||||
|
pager-hierarchy=## Pager Hierarchy
|
||||||
|
shell-aliases=## 4.11 Shell Aliases
|
||||||
|
kitty-logging=### kitty-logging
|
||||||
|
watcher=### kitty-logging
|
||||||
|
|
||||||
|
# ── Section 6: Dependency Catalog ────────────────────────────
|
||||||
|
catalog=# 6. DEPENDENCY CATALOG
|
||||||
|
deps-catalog=# 6. DEPENDENCY CATALOG
|
||||||
|
required=## Required
|
||||||
|
integrations=## Integrations
|
||||||
|
recommended=## Recommended
|
||||||
|
install-methods=## Install Methods
|
||||||
|
|
||||||
|
# ── Section 7: Customization ──────────────────────────────────
|
||||||
|
customization=# 7. CUSTOMIZATION
|
||||||
|
customize=# 7. CUSTOMIZATION
|
||||||
|
local=## Machine-local Configuration
|
||||||
|
user-dots=## Machine-local Configuration
|
||||||
|
dots-link=## Machine-local Configuration
|
||||||
|
secrets=## Secrets and API Keys
|
||||||
|
overrides=## Overriding Configuration Variables
|
||||||
|
universal=## Fish Universal Variables
|
||||||
|
opinionated=## Opinionated Components (Minimal Mode)
|
||||||
|
minimal=## Opinionated Components (Minimal Mode)
|
||||||
|
minimal-mode=## Opinionated Components (Minimal Mode)
|
||||||
|
opt-out=## Opinionated Components (Minimal Mode)
|
||||||
|
toggles=## Opinionated Components (Minimal Mode)
|
||||||
|
component-reference=# 8. COMPONENTS REFERENCE
|
||||||
|
components=# 8. COMPONENTS REFERENCE
|
||||||
|
c1=## C1 — Command Shadows
|
||||||
|
command-shadows=## C1 — Command Shadows
|
||||||
|
aliases-detail=## C1 — Command Shadows
|
||||||
|
c2=## C2 — Startup Side-Effects
|
||||||
|
autoexec=## C2 — Startup Side-Effects
|
||||||
|
startup=## C2 — Startup Side-Effects
|
||||||
|
c3=## C3 — Key and Environment Overrides
|
||||||
|
overrides-detail=## C3 — Key and Environment Overrides
|
||||||
|
bang-bang=## C3 — Key and Environment Overrides
|
||||||
|
c4=## C4 — Terminal and Tool Integration
|
||||||
|
integrations-detail=## C4 — Terminal and Tool Integration
|
||||||
|
c5=## C5 — Logging and Capture
|
||||||
|
logging-detail=## C5 — Logging and Capture
|
||||||
|
logging-sentinel=## C5 — Logging and Capture
|
||||||
|
zellij=## C5 — Logging and Capture
|
||||||
|
zellij-logging=## C5 — Logging and Capture
|
||||||
|
tmux-logging=## C5 — Logging and Capture
|
||||||
|
pipe-pane=## C5 — Logging and Capture
|
||||||
|
dump-screen=## C5 — Logging and Capture
|
||||||
|
c6=## C6 — Greeting and First-Run UI
|
||||||
|
greeting=## C6 — Greeting and First-Run UI
|
||||||
|
|
||||||
|
# ── Prompt and Theme ──────────────────────────────────────────
|
||||||
|
prompt-theme=## Prompt and Theme
|
||||||
|
starship=### Starship
|
||||||
|
fallback-prompt=### Catppuccin Fallback Prompt
|
||||||
|
catppuccin-prompt=### Catppuccin Fallback Prompt
|
||||||
|
nim-prompt=### Catppuccin Fallback Prompt
|
||||||
|
fzf-theme=### FZF
|
||||||
|
catppuccin-theme=### Catppuccin Mocha Syntax Highlighting
|
||||||
|
|
||||||
|
# ── Section 9: Fisher Plugins ─────────────────────────────────
|
||||||
|
plugins=# 9. FISHER PLUGINS
|
||||||
|
fisher=# 9. FISHER PLUGINS
|
||||||
|
fisher-managed=## Fisher-Managed Plugins
|
||||||
|
sponge=## Fisher-Managed Plugins
|
||||||
|
sponge-filtering=## Sponge History Filtering
|
||||||
|
history-filtering=## Sponge History Filtering
|
||||||
|
privacy=## Sponge History Filtering
|
||||||
|
__fish_sponge_extra_sensitive=## Sponge History Filtering
|
||||||
|
extra-sensitive=## Sponge History Filtering
|
||||||
|
sponge-settings=### config-settings
|
||||||
|
bundled-plugins=## Bundled Plugin Functionality
|
||||||
|
fish-plugins-manifest=## fish_plugins Manifest
|
||||||
|
|
||||||
|
# ── Section 10: Installation ────────────────────────────────────
|
||||||
|
installation=# 10. INSTALLATION
|
||||||
|
install=# 10. INSTALLATION
|
||||||
|
sentinel=## Return Sentinel
|
||||||
|
updating=## Updating
|
||||||
|
|
||||||
|
# ── Section 11: Personalization ───────────────────────────────
|
||||||
|
personalization=# 11. PERSONALIZATION
|
||||||
|
personalize=# 11. PERSONALIZATION
|
||||||
|
secrets-file=## secrets.fish
|
||||||
|
local-config=## local.fish
|
||||||
|
|
||||||
|
# ── Section 12: Troubleshooting ──────────────────────────────
|
||||||
|
troubleshooting=# 12. TROUBLESHOOTING
|
||||||
|
troubleshoot=# 12. TROUBLESHOOTING
|
||||||
|
faq=# 12. TROUBLESHOOTING
|
||||||
|
uninstall=## Uninstalling and Reverting to Backup
|
||||||
|
revert=## Uninstalling and Reverting to Backup
|
||||||
|
fish-version=## Fish Version Requirement
|
||||||
|
version-req=## Fish Version Requirement
|
||||||
|
disable-logging=## Enable or Disable Session Logging
|
||||||
|
enable-logging=## Enable or Disable Session Logging
|
||||||
|
disable-greeting=## Change or Disable the Greeting
|
||||||
|
change-greeting=## Change or Disable the Greeting
|
||||||
|
secrets-trouble=## Secrets and Machine-Local Configuration
|
||||||
|
local-trouble=## Secrets and Machine-Local Configuration
|
||||||
|
return-sentinel=## Tool Init Does Nothing (Return Sentinel)
|
||||||
|
tool-init=## Tool Init Does Nothing (Return Sentinel)
|
||||||
|
missing-deps=## Missing Dependencies
|
||||||
|
vi-mode=## Vi Mode Keybindings
|
||||||
|
vi-trouble=## Vi Mode Keybindings
|
||||||
|
emacs-mode=## Vi Mode Keybindings
|
||||||
|
minimal-trouble=## What's with the C1-C6 stuff?
|
||||||
|
|
||||||
|
# ── Section 13: Viewing This Manual ──────────────────────────
|
||||||
|
viewing=# 13. VIEWING THIS MANUAL
|
||||||
|
manual=# 13. VIEWING THIS MANUAL
|
||||||
|
ov=## In the terminal
|
||||||
|
man-page=## As a man page
|
||||||
|
manpage=## As a man page
|
||||||
|
jump=## In the terminal
|
||||||
|
html=## The documentation website
|
||||||
|
browser=## The documentation website
|
||||||
|
site=## The documentation website
|
||||||
|
|
||||||
|
|
||||||
+3751
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: Name
|
||||||
|
manTitle: NAME
|
||||||
|
man: true
|
||||||
|
site: false
|
||||||
|
sidebar:
|
||||||
|
order: 1
|
||||||
|
---
|
||||||
|
|
||||||
|
fish-config - personal fish shell configuration for Fish 4.x with modern CLI tool integration
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
title: Synopsis
|
||||||
|
manTitle: SYNOPSIS
|
||||||
|
man: true
|
||||||
|
site: false
|
||||||
|
sidebar:
|
||||||
|
order: 2
|
||||||
|
---
|
||||||
|
|
||||||
|
help config [SECTION]
|
||||||
|
|
||||||
|
Open this manual in the best available pager. Optionally jump to a section
|
||||||
|
by keyword:
|
||||||
|
|
||||||
|
help config keybindings
|
||||||
|
help config pkg
|
||||||
|
help config abbreviations
|
||||||
|
help config logs
|
||||||
|
|
||||||
|
The `help config` syntax integrates with fish's built-in help command.
|
||||||
|
The underlying `config-help` function is also available directly.
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
---
|
||||||
|
title: Table Of Contents
|
||||||
|
manTitle: TABLE OF CONTENTS
|
||||||
|
man: true
|
||||||
|
site: false
|
||||||
|
sidebar:
|
||||||
|
order: 4
|
||||||
|
---
|
||||||
|
|
||||||
|
1. Configuration Variables
|
||||||
|
2. PATH Setup
|
||||||
|
3. Key Bindings
|
||||||
|
4. Abbreviations
|
||||||
|
4.1 Editors
|
||||||
|
4.2 Navigation and Listing
|
||||||
|
4.3 Git
|
||||||
|
4.4 Terminal Windows, Tabs, and Panes
|
||||||
|
4.5 Chezmoi
|
||||||
|
4.6 Docker
|
||||||
|
4.7 Systemctl
|
||||||
|
4.8 AI Assistants
|
||||||
|
4.9 History Expansion
|
||||||
|
4.10 Miscellaneous
|
||||||
|
4.11 Shell Aliases
|
||||||
|
5. Functions Reference
|
||||||
|
5.1 File and Directory
|
||||||
|
5.2 Navigation
|
||||||
|
5.3 Editors and Viewers
|
||||||
|
5.4 Git and Version Control
|
||||||
|
5.5 Package Management
|
||||||
|
5.6 Dependency Management
|
||||||
|
5.7 System and Monitoring
|
||||||
|
5.8 Terminal Management
|
||||||
|
5.9 Clipboard
|
||||||
|
5.10 Network
|
||||||
|
5.11 Pager and Logging
|
||||||
|
5.12 AI and Developer Tools
|
||||||
|
5.13 Media and Utilities
|
||||||
|
5.14 Miscellaneous
|
||||||
|
6. Dependency Catalog
|
||||||
|
7. Customization
|
||||||
|
8. Fisher Plugins
|
||||||
|
9. Installation
|
||||||
|
10. Personalization
|
||||||
|
11. Troubleshooting
|
||||||
|
11.1 Uninstalling and Reverting to Backup
|
||||||
|
11.2 Fish Version Requirement
|
||||||
|
11.3 Enable or Disable Session Logging
|
||||||
|
11.4 Change or Disable the Greeting
|
||||||
|
11.5 Secrets and Machine-Local Configuration
|
||||||
|
11.6 Tool Init Does Nothing (Return Sentinel)
|
||||||
|
11.7 Missing Dependencies
|
||||||
|
11.8 Vi Mode Keybindings
|
||||||
|
11.9 What's with the C1-C6 stuff?
|
||||||
|
12. Viewing This Manual
|
||||||
|
|
||||||
|
---
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
---
|
||||||
|
title: Configuration Variables
|
||||||
|
manTitle: 1. CONFIGURATION VARIABLES
|
||||||
|
sidebar:
|
||||||
|
order: 5
|
||||||
|
helpKeywords:
|
||||||
|
- variables
|
||||||
|
- config
|
||||||
|
---
|
||||||
|
|
||||||
|
These variables are exported from config.fish on every interactive session.
|
||||||
|
Override them in local.fish (see Section 10, Personalization).
|
||||||
|
|
||||||
|
## Environment Directories (XDG)
|
||||||
|
|
||||||
|
| Variable | Value |
|
||||||
|
|---|---|
|
||||||
|
| `XDG_CONFIG_HOME` | `~/.config` |
|
||||||
|
| `XDG_CACHE_HOME` | `~/.cache` |
|
||||||
|
| `XDG_DATA_HOME` | `~/.local/share` |
|
||||||
|
| `XDG_STATE_HOME` | `~/.local/state` |
|
||||||
|
|
||||||
|
Tools that respect XDG are directed to these paths rather than polluting `$HOME`.
|
||||||
|
|
||||||
|
## Tool Homes (XDG-compliant)
|
||||||
|
|
||||||
|
| Variable | Value |
|
||||||
|
|---|---|
|
||||||
|
| `CARGO_HOME` | `$XDG_DATA_HOME/cargo` |
|
||||||
|
| `RUSTUP_HOME` | `$XDG_DATA_HOME/rustup` |
|
||||||
|
| `GOPATH` | `$XDG_DATA_HOME/go` |
|
||||||
|
| `BUN_INSTALL` | `$XDG_DATA_HOME/bun` |
|
||||||
|
| `NPM_CONFIG_PREFIX` | `$XDG_DATA_HOME/npm-global` |
|
||||||
|
| `GNUPGHOME` | `$XDG_CONFIG_HOME/gnupg` |
|
||||||
|
| `WAKATIME_HOME` | `$XDG_CONFIG_HOME/wakatime` |
|
||||||
|
|
||||||
|
## Editor and Pager
|
||||||
|
|
||||||
|
| Variable | Value / Notes |
|
||||||
|
|---|---|
|
||||||
|
| `EDITOR` | `nvim` (falls back to `vi` if `nvim` is absent) |
|
||||||
|
| `VISUAL` | unset by default; set a GUI editor via `local.fish` (the `edit` function falls back to a GUI chain when `VISUAL` is empty) |
|
||||||
|
| `SUDO_EDITOR` | same as `EDITOR` |
|
||||||
|
| `PAGER` | `ov` (falls back to `less`) |
|
||||||
|
|
||||||
|
## Scrollback History
|
||||||
|
|
||||||
|
| Variable | Value / Notes |
|
||||||
|
|---|---|
|
||||||
|
| `__fish_scrollback_history_dir` | (unset → `~/.terminal_history`) |
|
||||||
|
| `__fish_scrollback_history_max_files` | (unset → `100`) |
|
||||||
|
| `SCROLLBACK_HISTORY_DIR` | `~/.terminal_history` (exported mirror) |
|
||||||
|
| `SCROLLBACK_HISTORY_MAX_FILES` | `100` (exported mirror) |
|
||||||
|
|
||||||
|
The `__fish_scrollback_history_*` universal variables are the fish-style source
|
||||||
|
of truth — set them via `config-settings` → Paths, or `set -U` directly.
|
||||||
|
`config.fish` exports the `SCROLLBACK_HISTORY_*` mirrors from them, because the
|
||||||
|
POSIX wrapper scripts (`paru`/`yay`/`tmux`/`zellij` logging and `_prune_terminal_logs`)
|
||||||
|
read the exported names from the environment. When the `__fish_` vars are unset,
|
||||||
|
the documented defaults are exported. `config.fish` deliberately does not create
|
||||||
|
a global source var, which would shadow the universal and stop live edits from
|
||||||
|
taking effect.
|
||||||
|
|
||||||
|
Scrollback logs accumulate in `SCROLLBACK_HISTORY_DIR` as timestamped files.
|
||||||
|
When the count exceeds `SCROLLBACK_HISTORY_MAX_FILES` the oldest are pruned
|
||||||
|
automatically on exit. Use `logs` to browse them interactively.
|
||||||
|
|
||||||
|
## Other
|
||||||
|
|
||||||
|
| Variable | Value | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| `GPG_TTY` | `$(tty)` | ensures GPG passphrase prompts work |
|
||||||
|
| `CLAUDE_CODE_NO_FLICKER` | `1` | suppress terminal flicker in Claude Code |
|
||||||
|
| `CDPATH` | `. ~/projects ~` | |
|
||||||
|
|
||||||
|
Opinionated defaults (`CDPATH`, `PAGER`/`MANPAGER`, Vi mode, command shadows,
|
||||||
|
terminal integrations) can be switched off per category with universal
|
||||||
|
variables — see Section 7, "Opinionated Components (Minimal Mode)".
|
||||||
|
|
||||||
|
## Pager Hierarchy
|
||||||
|
|
||||||
|
`$PAGER` is set to `ov` when available, falling back to `less`. The `less` wrapper
|
||||||
|
function extends this into a full chain so anything that calls `less` directly
|
||||||
|
also benefits:
|
||||||
|
|
||||||
|
`$PAGER` → `ov` → `less` → `more` → `cat`
|
||||||
|
|
||||||
|
When `bat` is installed, man pages are rendered with syntax highlighting:
|
||||||
|
|
||||||
|
| Variable | Value |
|
||||||
|
|---|---|
|
||||||
|
| `MANROFFOPT` | `-c` |
|
||||||
|
| `MANPAGER` | `sh -c 'col -bx \| bat -l man -p'` |
|
||||||
|
|
||||||
|
## Integrations
|
||||||
|
|
||||||
|
### Zoxide
|
||||||
|
|
||||||
|
`cd`, `z`, and `cdi`/`zi` are all mapped to `zoxide`-backed navigation. Tab completions
|
||||||
|
for `cd` and `z` blend standard directory entries (CWD and `CDPATH`) with frecency
|
||||||
|
results so both familiar and frequently-visited paths appear in one list.
|
||||||
|
|
||||||
|
### DirEnv
|
||||||
|
|
||||||
|
Automatically loads `.envrc` files on directory change. Takes priority over
|
||||||
|
the auto-venv logic — if a directory is managed by `direnv`, the auto-venv
|
||||||
|
activation is skipped entirely.
|
||||||
|
|
||||||
|
### Auto Python Venv
|
||||||
|
|
||||||
|
When entering a directory that contains a `.venv/`, the virtualenv is activated
|
||||||
|
automatically and deactivated when you leave the project tree.
|
||||||
|
|
||||||
|
### WakaTime
|
||||||
|
|
||||||
|
Every shell command is reported to WakaTime for time-tracking. Set
|
||||||
|
`FISH_WAKATIME_DISABLED=1` to disable without removing the plugin.
|
||||||
|
|
||||||
|
### Tailscale
|
||||||
|
|
||||||
|
Full tab completion for the `tailscale` CLI is provided via `conf.d/tailscale.fish`.
|
||||||
|
|
||||||
|
### Done Notifications
|
||||||
|
|
||||||
|
Desktop notifications fire when a command takes longer than 10 seconds and
|
||||||
|
the terminal window is not focused. Configured via fish universal variables:
|
||||||
|
|
||||||
|
| Variable | Value |
|
||||||
|
|---|---|
|
||||||
|
| `__done_min_cmd_duration` | `10000` ms |
|
||||||
|
| `__done_notification_urgency_level` | `low` |
|
||||||
|
|
||||||
|
### Scrollback History
|
||||||
|
|
||||||
|
When running inside Kitty, closing a shell session via `exit` saves a timestamped
|
||||||
|
scrollback snapshot to `SCROLLBACK_HISTORY_DIR`. Files are named:
|
||||||
|
|
||||||
|
`scrollback_YYYY-MM-DD_HH-MM-SS.log`
|
||||||
|
|
||||||
|
The `paru` and `yay` wrappers (auto-generated in `~/.local/bin/`) run the command
|
||||||
|
inside a PTY via `script(1)` so download progress bars are preserved on screen,
|
||||||
|
then render the captured terminal animation down to a clean static log via
|
||||||
|
`scripts/clean_progress_log.py` (a small terminal-screen emulator that replays
|
||||||
|
cursor movements, collapses repainted progress frames to their final state,
|
||||||
|
and preserves ANSI color). If `python3` is unavailable the wrapper falls back to
|
||||||
|
dropping only the `script(1)` header/footer. Output is saved to:
|
||||||
|
|
||||||
|
- `paru_YYYY-MM-DD_HH-MM-SS.log`
|
||||||
|
- `yay_YYYY-MM-DD_HH-MM-SS.log`
|
||||||
|
|
||||||
|
Before pruning, `_scrollback_prune_junk` silently removes empty files, files
|
||||||
|
with only a single meaningful line (e.g. bare `[exited]` captures), and Kitty
|
||||||
|
tab-rename prompt captures. Use `exit --no-log` (or `exit -n`) to skip capture.
|
||||||
|
|
||||||
|
---
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
title: PATH Setup
|
||||||
|
manTitle: 2. PATH SETUP
|
||||||
|
sidebar:
|
||||||
|
order: 6
|
||||||
|
helpKeywords:
|
||||||
|
- path
|
||||||
|
---
|
||||||
|
|
||||||
|
Directories prepended to PATH in this order (first wins):
|
||||||
|
|
||||||
|
| Directory | Purpose |
|
||||||
|
|---|---|
|
||||||
|
| `~/.local/bin` | Standard user-local executables |
|
||||||
|
| `~/Applications` | User-installed standalone apps |
|
||||||
|
| `~/scripts` | Personal shell scripts |
|
||||||
|
| `~/bin` | Cargo binaries (appended — lowest priority) |
|
||||||
|
| `$BUN_INSTALL/bin` | Bun runtime and global packages |
|
||||||
|
| `$NPM_CONFIG_PREFIX/bin` | Global npm packages |
|
||||||
|
| `~/.lmstudio/bin` | LM Studio CLI |
|
||||||
|
| `~/.resend/bin` | Resend CLI |
|
||||||
|
| `~/.fzf/bin` | `fzf` binary (git-installed) |
|
||||||
|
|
||||||
|
Cargo binaries are intentionally appended (lowest priority) to avoid
|
||||||
|
shadowing system-installed Rust tools.
|
||||||
|
|
||||||
|
NOTE: While these directories are merged with your system's existing `$PATH` values, any executables in the prepended directories above will override (shadow) system binaries of the same name.
|
||||||
|
|
||||||
|
TIP: This standard PATH setup is gated behind the opinionated component overrides toggle. If you prefer to manage your PATH completely manually, you can disable it by setting `__fish_config_op_overrides` to `0` (or toggle it off in the `config-settings` menu).
|
||||||
|
|
||||||
|
---
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
---
|
||||||
|
title: Key Bindings
|
||||||
|
manTitle: 3. KEY BINDINGS
|
||||||
|
sidebar:
|
||||||
|
order: 7
|
||||||
|
helpKeywords:
|
||||||
|
- keybindings
|
||||||
|
- bindings
|
||||||
|
- key-bindings
|
||||||
|
- keys
|
||||||
|
---
|
||||||
|
|
||||||
|
The shell uses Vi key bindings (fish_vi_key_bindings). All custom bindings
|
||||||
|
are active in Insert, Normal, and Visual modes unless noted.
|
||||||
|
|
||||||
|
Binding Action
|
||||||
|
─────────────────────────────────────────────────────────────────────
|
||||||
|
Ctrl+G Insert the head of the previous command's last path
|
||||||
|
argument. Equivalent to !$:h in Bash.
|
||||||
|
Example: previous = "cd /usr/local/bin"
|
||||||
|
Ctrl+G inserts "/usr/local"
|
||||||
|
|
||||||
|
Ctrl+F Interactive history substitution. Type old/new then
|
||||||
|
press Ctrl+F to apply s/old/new/ to the previous
|
||||||
|
command. Equivalent to !!:s/old/new/ in Bash.
|
||||||
|
Example: previous = "echo this is a test"
|
||||||
|
type "this is/that was", press Ctrl+F
|
||||||
|
result = "echo that was a test"
|
||||||
|
|
||||||
|
Ctrl+Alt+U Strip the first token of the current command line,
|
||||||
|
leaving arguments in place with the cursor at the
|
||||||
|
start. Useful for quickly retyping the command.
|
||||||
|
Example: "mkdir new_folder" -> " new_folder"
|
||||||
|
|
||||||
|
Ctrl+Alt+= Evaluate the current command line buffer with
|
||||||
|
Qalculate! (qalc) and print the result inline.
|
||||||
|
Requires qalc to be installed.
|
||||||
|
Example: type "150 * 1.08", press Ctrl+Alt+=
|
||||||
|
prints 162
|
||||||
|
|
||||||
|
Ctrl+Enter Smart execute: runs commands instantly without
|
||||||
|
pressing Enter a second time for certain fast-path
|
||||||
|
commands (speedtest-fast, etc.).
|
||||||
|
|
||||||
|
@@ FZF inline picker. Type @@ anywhere on the command
|
||||||
|
line to open an fzf picker and insert a selection
|
||||||
|
at the cursor position.
|
||||||
|
|
||||||
|
Ctrl+Right Accept autosuggestion one word/directory segment
|
||||||
|
at a time. (Restores Fish 3.x behavior by binding
|
||||||
|
to nextd-or-forward-word).
|
||||||
|
|
||||||
|
## FZF Bindings (bundled from PatrickF1/fzf.fish)
|
||||||
|
|
||||||
|
Ctrl+R Search command history
|
||||||
|
Ctrl+Alt+F Search git-tracked files
|
||||||
|
Ctrl+Alt+L Search git log
|
||||||
|
Ctrl+Alt+S Search git status
|
||||||
|
Ctrl+V Search shell variables
|
||||||
|
Ctrl+Alt+P Search running processes
|
||||||
|
|
||||||
|
---
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
title: Editors
|
||||||
|
manTitle: 4.1 Editors
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- GENERATED: Editors -->
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
title: Navigation and Listing
|
||||||
|
manTitle: 4.2 Navigation and Listing
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- GENERATED: Navigation and Listing -->
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
title: Git
|
||||||
|
manTitle: 4.3 Git
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- GENERATED: Git -->
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: Terminal Windows, Tabs, and Panes
|
||||||
|
manTitle: 4.4 Terminal Windows, Tabs, and Panes
|
||||||
|
---
|
||||||
|
|
||||||
|
These abbreviations control the terminal emulator. Each has a Kitty
|
||||||
|
variant and a WezTerm variant; the correct one is inserted based on
|
||||||
|
`$TERM` or `$TERM_PROGRAM`.
|
||||||
|
|
||||||
|
<!-- GENERATED: Terminal Windows, Tabs, and Panes -->
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
title: Chezmoi
|
||||||
|
manTitle: 4.5 Chezmoi
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- GENERATED: Chezmoi -->
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
title: Docker
|
||||||
|
manTitle: 4.6 Docker
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- GENERATED: Docker -->
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
title: Systemctl
|
||||||
|
manTitle: 4.7 Systemctl
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- GENERATED: Systemctl -->
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
title: AI Assistants
|
||||||
|
manTitle: 4.8 AI Assistants
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- GENERATED: AI Assistants -->
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: History Expansion
|
||||||
|
manTitle: 4.9 History Expansion
|
||||||
|
---
|
||||||
|
|
||||||
|
Bash-style history expansions trigger on Space or Enter. Some are implemented
|
||||||
|
as abbreviations (e.g. `!*`), while others (`!!`, `!$`, `!.`) are implemented
|
||||||
|
as keybindings, but they all serve the same purpose.
|
||||||
|
|
||||||
|
<!-- GENERATED: History Expansion -->
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
title: Miscellaneous
|
||||||
|
manTitle: 4.10 Miscellaneous
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- GENERATED: Miscellaneous -->
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
title: Shell Aliases
|
||||||
|
manTitle: 4.11 Shell Aliases
|
||||||
|
---
|
||||||
|
|
||||||
|
These aliases are defined in conf.d/tricks.fish via alias (which creates Fish
|
||||||
|
functions). They are active in all interactive sessions.
|
||||||
|
|
||||||
|
<!-- GENERATED: Shell Aliases -->
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
title: Abbreviations
|
||||||
|
manTitle: 4. ABBREVIATIONS
|
||||||
|
sidebar:
|
||||||
|
order: 8
|
||||||
|
helpKeywords:
|
||||||
|
- abbreviations
|
||||||
|
- abbr
|
||||||
|
- abbrs
|
||||||
|
---
|
||||||
|
|
||||||
|
Abbreviations expand when you press Space or Enter. They are terminal-aware:
|
||||||
|
some expand differently in Kitty vs WezTerm vs other terminals.
|
||||||
|
|
||||||
|
<CardGrid>
|
||||||
|
<LinkCard title="Editors" href="/04-abbreviations/01-editors/" />
|
||||||
|
<LinkCard title="Navigation and Listing" href="/04-abbreviations/02-navigation-and-listing/" />
|
||||||
|
<LinkCard title="Git" href="/04-abbreviations/03-git/" />
|
||||||
|
<LinkCard title="Terminal Windows, Tabs, and Panes" href="/04-abbreviations/04-terminal-windows-tabs-and-panes/" />
|
||||||
|
<LinkCard title="Chezmoi" href="/04-abbreviations/05-chezmoi/" />
|
||||||
|
<LinkCard title="Docker" href="/04-abbreviations/06-docker/" />
|
||||||
|
<LinkCard title="Systemctl" href="/04-abbreviations/07-systemctl/" />
|
||||||
|
<LinkCard title="AI Assistants" href="/04-abbreviations/08-ai-assistants/" />
|
||||||
|
<LinkCard title="History Expansion" href="/04-abbreviations/09-history-expansion/" />
|
||||||
|
<LinkCard title="Miscellaneous" href="/04-abbreviations/10-miscellaneous/" />
|
||||||
|
<LinkCard title="Shell Aliases" href="/04-abbreviations/11-shell-aliases/" />
|
||||||
|
</CardGrid>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: File and Directory
|
||||||
|
manTitle: 5.1 File and Directory
|
||||||
|
sidebar:
|
||||||
|
order: 1
|
||||||
|
helpKeywords:
|
||||||
|
- files
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: Navigation
|
||||||
|
manTitle: 5.2 Navigation
|
||||||
|
sidebar:
|
||||||
|
order: 2
|
||||||
|
helpKeywords:
|
||||||
|
- nav-fns
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: Editors and Viewers
|
||||||
|
manTitle: 5.3 Editors and Viewers
|
||||||
|
sidebar:
|
||||||
|
order: 3
|
||||||
|
helpKeywords:
|
||||||
|
- editors
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: Git and Version Control
|
||||||
|
manTitle: 5.4 Git and Version Control
|
||||||
|
sidebar:
|
||||||
|
order: 4
|
||||||
|
helpKeywords:
|
||||||
|
- git
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: Package Management
|
||||||
|
manTitle: 5.5 Package Management
|
||||||
|
sidebar:
|
||||||
|
order: 5
|
||||||
|
helpKeywords:
|
||||||
|
- package-manager
|
||||||
|
- packages
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: Dependency Management
|
||||||
|
manTitle: 5.6 Dependency Management
|
||||||
|
sidebar:
|
||||||
|
order: 6
|
||||||
|
helpKeywords:
|
||||||
|
- deps
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: System and Monitoring
|
||||||
|
manTitle: 5.7 System and Monitoring
|
||||||
|
sidebar:
|
||||||
|
order: 7
|
||||||
|
helpKeywords:
|
||||||
|
- system
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: Terminal Management
|
||||||
|
manTitle: 5.8 Terminal Management
|
||||||
|
sidebar:
|
||||||
|
order: 8
|
||||||
|
helpKeywords:
|
||||||
|
- terminal-mgmt
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: Clipboard
|
||||||
|
manTitle: 5.9 Clipboard
|
||||||
|
sidebar:
|
||||||
|
order: 9
|
||||||
|
helpKeywords:
|
||||||
|
- clipboard
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: Network
|
||||||
|
manTitle: 5.10 Network
|
||||||
|
sidebar:
|
||||||
|
order: 10
|
||||||
|
helpKeywords:
|
||||||
|
- network
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: Pager and Logging
|
||||||
|
manTitle: 5.11 Pager and Logging
|
||||||
|
sidebar:
|
||||||
|
order: 11
|
||||||
|
helpKeywords:
|
||||||
|
- logging
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: AI and Developer Tools
|
||||||
|
manTitle: 5.12 AI and Developer Tools
|
||||||
|
sidebar:
|
||||||
|
order: 12
|
||||||
|
helpKeywords:
|
||||||
|
- ai
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: Media and Utilities
|
||||||
|
manTitle: 5.13 Media and Utilities
|
||||||
|
sidebar:
|
||||||
|
order: 13
|
||||||
|
helpKeywords:
|
||||||
|
- media
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: Miscellaneous
|
||||||
|
manTitle: 5.14 Miscellaneous
|
||||||
|
sidebar:
|
||||||
|
order: 14
|
||||||
|
helpKeywords:
|
||||||
|
- miscfns
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: Functions Reference
|
||||||
|
manTitle: 5. FUNCTIONS REFERENCE
|
||||||
|
sidebar:
|
||||||
|
order: 9
|
||||||
|
helpKeywords:
|
||||||
|
- functions
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
---
|
||||||
|
title: Dependency Catalog
|
||||||
|
manTitle: 6. DEPENDENCY CATALOG
|
||||||
|
sidebar:
|
||||||
|
order: 10
|
||||||
|
helpKeywords:
|
||||||
|
- catalog
|
||||||
|
- deps-catalog
|
||||||
|
---
|
||||||
|
|
||||||
|
fish-deps manages these tools. Run `fish-deps` to check status, or
|
||||||
|
`fish-deps install` to install missing ones.
|
||||||
|
|
||||||
|
## Required
|
||||||
|
|
||||||
|
| Tool | Description |
|
||||||
|
|---|---|
|
||||||
|
| `fish` | Fish shell >= 4.0 |
|
||||||
|
| `fzf` | Fuzzy finder |
|
||||||
|
|
||||||
|
## Integrations
|
||||||
|
|
||||||
|
| Tool | Description |
|
||||||
|
|---|---|
|
||||||
|
| `wakatime` | Developer time tracking |
|
||||||
|
| `tailscale` | Mesh VPN client |
|
||||||
|
|
||||||
|
## Recommended
|
||||||
|
|
||||||
|
| Tool | Description |
|
||||||
|
|---|---|
|
||||||
|
| `cargo` | Rust toolchain (via rustup); used by `fish-deps` to install Rust-based tools and to build fish from source. All paths are gated on `type -q cargo` and degrade gracefully. |
|
||||||
|
| `starship` | Cross-shell prompt; loaded via `type -q starship` guard. Without it the Catppuccin nim-style fallback prompt activates. |
|
||||||
|
| `uv` | Python package and project manager (Astral); used by the fish-from-source build path in `fish-deps`. All consumers degrade gracefully without it. |
|
||||||
|
| `direnv` | Per-directory environment loading; integration is fully guarded with `type -q direnv`. Without it the direnv hook is simply not loaded and auto-venv activates normally. |
|
||||||
|
| `paru` | AUR helper (Arch only; preferred); guarded throughout — non-Arch systems silently skip AUR-specific paths. |
|
||||||
|
| `yay` | AUR helper (Arch only; fallback to paru); same guards apply. |
|
||||||
|
| `eza` | Modern `ls` replacement |
|
||||||
|
| `zoxide` | Smart cd with frecency |
|
||||||
|
| `lsd` | `ls` replacement (fallback to `eza`) |
|
||||||
|
| `bat` | Syntax-highlighted `cat` |
|
||||||
|
| `btop` | Modern resource monitor |
|
||||||
|
| `dust` | Disk usage tree (Rust) |
|
||||||
|
| `duf` | Disk usage/free overview |
|
||||||
|
| `prettyping` | Colorized ping wrapper |
|
||||||
|
| `ov` | Modern pager (replaces `less`) |
|
||||||
|
| `ripgrep` | Fast line search |
|
||||||
|
| `lazygit` | Terminal git UI |
|
||||||
|
| `lazydocker` | Terminal docker UI |
|
||||||
|
| `trash` | Safe delete (`trash-cli`) |
|
||||||
|
| `kitty` | GPU-accelerated terminal (primary) |
|
||||||
|
| `wezterm` | GPU-accelerated terminal (alternative) |
|
||||||
|
| `python3` | Standalone interpreter — used by the `paru`/`yay` log cleaner. Note: `uv` does not provide `python3` on PATH, and Arch's base does not include it, so it is listed separately. All consumers degrade gracefully without it. |
|
||||||
|
| `yt-dlp` | Video/media downloader; backs the `yt-dlp` wrapper function. Optional — the wrapper falls back to the system `yt-dlp` and the rest of the config works without it. |
|
||||||
|
|
||||||
|
## Install Methods
|
||||||
|
|
||||||
|
The install priority for each tool:
|
||||||
|
|
||||||
|
| Method | Packages |
|
||||||
|
|---|---|
|
||||||
|
| `cargo` | Rust tools (`eza`, `lsd`, `bat`, `dust`, `ov`, `ripgrep`, `trashy`, `zoxide`, `starship`) — always gets the latest crate version |
|
||||||
|
| system PM | `paru` / `apt` / `brew` / `dnf` / etc. — for tools without a crate |
|
||||||
|
| `git clone` | `fzf` — installed from GitHub to `~/.fzf/` |
|
||||||
|
| `curl` | `starship` installer, `fisher` bootstrap, `uv` installer |
|
||||||
|
|
||||||
|
---
|
||||||
@@ -0,0 +1,212 @@
|
|||||||
|
---
|
||||||
|
title: Customization
|
||||||
|
manTitle: 7. CUSTOMIZATION
|
||||||
|
sidebar:
|
||||||
|
order: 11
|
||||||
|
helpKeywords:
|
||||||
|
- customization
|
||||||
|
- customize
|
||||||
|
---
|
||||||
|
This section explains how to adapt the configuration to your specific workflow, including local machine overrides and opinionated component toggles.
|
||||||
|
|
||||||
|
|
||||||
|
## Machine-local Configuration
|
||||||
|
|
||||||
|
Place machine-specific settings that should not be committed to git in:
|
||||||
|
|
||||||
|
$__fish_user_dots_path/local.fish
|
||||||
|
|
||||||
|
`__fish_user_dots_path` defaults to `~/.config/.user-dots/fish`. Set a
|
||||||
|
custom location with:
|
||||||
|
|
||||||
|
set -U __fish_user_dots_path /path/to/your/dots/fish
|
||||||
|
|
||||||
|
Typical uses: additional PATH entries, local aliases, hostname-specific env
|
||||||
|
vars, work-specific tool configs.
|
||||||
|
|
||||||
|
For convenience, a git-ignored `user-dots` symlink in the fish config
|
||||||
|
directory tracks `$__fish_user_dots_path` so the overlay can be browsed from
|
||||||
|
`~/.config/fish/`. It is created if missing and repointed if the path changes.
|
||||||
|
Opt out by setting `__fish_user_dots_symlink` to a falsy value, or toggling
|
||||||
|
"Dots link" off on the config-settings Paths page — this stops generation and
|
||||||
|
removes any existing link. It only ever manages a symlink and never clobbers a
|
||||||
|
real file or directory at that path.
|
||||||
|
|
||||||
|
|
||||||
|
## Secrets and API Keys
|
||||||
|
|
||||||
|
$__fish_user_dots_path/secrets.fish
|
||||||
|
|
||||||
|
Store API tokens, GPG keys, private credentials here. This file is never
|
||||||
|
committed. It is sourced by local.fish directly, not by config.fish.
|
||||||
|
|
||||||
|
`local.fish` is sourced at the end of config.fish on every interactive
|
||||||
|
session, so it and its companion secrets.fish can override anything set
|
||||||
|
earlier.
|
||||||
|
|
||||||
|
|
||||||
|
## Overriding Configuration Variables
|
||||||
|
|
||||||
|
Any variable set in local.fish after the main config loads takes effect.
|
||||||
|
Example: to increase the scrollback history limit:
|
||||||
|
|
||||||
|
# in local.fish
|
||||||
|
set -gx SCROLLBACK_HISTORY_MAX_FILES 200
|
||||||
|
|
||||||
|
|
||||||
|
## Fish Universal Variables
|
||||||
|
|
||||||
|
Some settings (fzf colors, theme) are stored in fish_variables via
|
||||||
|
`set -U`. These are machine-local and git-ignored. Do not commit
|
||||||
|
fish_variables.
|
||||||
|
|
||||||
|
|
||||||
|
## Opinionated Components (Minimal Mode)
|
||||||
|
|
||||||
|
Every opinionated piece of this config is active by default but can be
|
||||||
|
switched off through six category opt-out variables, each evaluated via
|
||||||
|
`__fish_variable_check`. Set a variable to any falsy value (0, false, no,
|
||||||
|
off, n) to disable its category; erase it or set a truthy value (1, true,
|
||||||
|
yes, on, y) to re-enable. Unset means enabled — except for C5 logging, which
|
||||||
|
is opt-in (see below).
|
||||||
|
|
||||||
|
An explicit per-category truthy value takes precedence over the master
|
||||||
|
switch: setting `__fish_config_opinionated`=0 disables all unset categories,
|
||||||
|
but a category with an explicit truthy value remains enabled regardless.
|
||||||
|
|
||||||
|
C5 (logging) is the one exception to "unset means enabled". Because it
|
||||||
|
writes terminal output to disk, it is opt-in: unset means disabled, and the
|
||||||
|
master switch cannot enable it. Only an explicit truthy value turns logging
|
||||||
|
on.
|
||||||
|
|
||||||
|
Variable Disables
|
||||||
|
────────────────────────────────────────
|
||||||
|
__fish_config_op_aliases Command shadows and flag injection:
|
||||||
|
ls->eza, cat->bat, cd->zoxide,
|
||||||
|
rm->trash, less->ov, top->btop,
|
||||||
|
ping->prettyping, ssh->kitten,
|
||||||
|
du->duf/dust, mkdir/bash wrappers,
|
||||||
|
history timestamps, grep/cp/mv/wget
|
||||||
|
flag injection, help intercept, claude
|
||||||
|
AGENTS.md auto-link
|
||||||
|
__fish_config_op_autoexec Startup side-effects: Fisher
|
||||||
|
bootstrap, theme apply, paru/yay
|
||||||
|
wrapper generation, auto venv
|
||||||
|
activation, WakaTime hook
|
||||||
|
__fish_config_op_overrides Key and env overrides: Vi mode,
|
||||||
|
exit->smart_exit, PAGER/MANPAGER,
|
||||||
|
CDPATH, bang-bang system, autopair,
|
||||||
|
puffer, starship prompt, theme
|
||||||
|
colors, FZF_DEFAULT_OPTS, right
|
||||||
|
prompt
|
||||||
|
__fish_config_op_integrations Terminal/tool coupling: Kitty/
|
||||||
|
WezTerm window abbreviations, done
|
||||||
|
notifications, spwin/tab/split,
|
||||||
|
hist, logs, upgrade, WakaTime
|
||||||
|
__fish_config_op_logging Logging & capture (OPT-IN — this one
|
||||||
|
is off unless explicitly enabled):
|
||||||
|
scrollback capture on exit, paru/yay
|
||||||
|
AUR log wrappers, Kitty watcher
|
||||||
|
capture; sentinel file coordinates
|
||||||
|
cross-process state
|
||||||
|
__fish_config_op_greeting Greeting & first-run UI: per-session
|
||||||
|
fish_greeting override (defines empty
|
||||||
|
function late in config.fish to
|
||||||
|
suppress distro greetings such as
|
||||||
|
CachyOS fastfetch); first-run welcome
|
||||||
|
banner in conf.d/first_run.fish
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
# Disable command shadows only (rm becomes plain rm again):
|
||||||
|
set -U __fish_config_op_aliases off
|
||||||
|
|
||||||
|
# Turn session logging on (opt-in; off until you do this):
|
||||||
|
set -U __fish_config_op_logging on
|
||||||
|
|
||||||
|
# Full minimal mode — disable all six categories at once:
|
||||||
|
set -U __fish_config_opinionated 0
|
||||||
|
|
||||||
|
# Re-enable everything (except C5 logging, which stays opt-in):
|
||||||
|
set -Ue __fish_config_opinionated
|
||||||
|
|
||||||
|
# Minimal mode but keep the greeting:
|
||||||
|
set -U __fish_config_opinionated 0
|
||||||
|
set -U __fish_config_op_greeting 1
|
||||||
|
# (erase both to go back to full-flavor defaults)
|
||||||
|
|
||||||
|
For an interactive alternative to setting these variables by hand, run
|
||||||
|
config-settings — a full-screen TUI that flips any category (including C5
|
||||||
|
logging) on or off, per session or universally. See its entry in Section 5.
|
||||||
|
|
||||||
|
NOTE:
|
||||||
|
- Command shadows (rm, cat, ls, ...) react immediately; conf.d-level components (bindings, prompt, abbreviations, hooks) take effect in new shells.
|
||||||
|
- With aliases disabled, rm falls back to bare `command rm` — files are deleted permanently, not trashed.
|
||||||
|
- Disabled integration commands (spwin, tab, split, hist, logs, upgrade) print an error naming the variable that disabled them.
|
||||||
|
- On CachyOS, the distro fish config's own aliases, history override, and bang-bang bindings are stripped per category as well.
|
||||||
|
|
||||||
|
|
||||||
|
## Prompt and Theme
|
||||||
|
|
||||||
|
### Starship
|
||||||
|
|
||||||
|
The primary prompt is Starship, initialized by conf.d/starship.fish.
|
||||||
|
Configure it via ~/.config/starship.toml.
|
||||||
|
|
||||||
|
conf.d/starship.fish defines a fish_prompt wrapper that only activates when
|
||||||
|
starship is in PATH. It emits OSC 133;A (prompt start) immediately before
|
||||||
|
Starship renders and OSC 133;B (input start) immediately after, placing both
|
||||||
|
markers on the prompt line itself. This allows ov to use them as sticky
|
||||||
|
section headers when browsing scrollback logs. Without Starship, fish's
|
||||||
|
built-in prompt handles these markers automatically.
|
||||||
|
|
||||||
|
### Catppuccin Fallback Prompt
|
||||||
|
|
||||||
|
When Starship is absent or C3 overrides are disabled, a built-in nim-style
|
||||||
|
two-line prompt activates from functions/fish_prompt.fish. No external
|
||||||
|
dependencies — fish builtins only.
|
||||||
|
|
||||||
|
Layout:
|
||||||
|
|
||||||
|
┬─[user@host:~/path] (main)
|
||||||
|
╰─>$
|
||||||
|
|
||||||
|
Elements:
|
||||||
|
|
||||||
|
user Yellow (Catppuccin Yellow); red if root
|
||||||
|
@host Blue (local) or Teal (SSH)
|
||||||
|
~/path prompt_pwd abbreviation (Catppuccin Text)
|
||||||
|
(main) Current git branch in Catppuccin Pink; omitted outside repos
|
||||||
|
─[V:name] Active Python venv basename; omitted when none
|
||||||
|
─[N/I/R/V] Vi-mode indicator when vi bindings are active
|
||||||
|
┬─ / ╰─> Connector lines: Catppuccin Green on success, Red on failure
|
||||||
|
|
||||||
|
The right prompt (fish_right_prompt.fish) always renders, regardless of C3
|
||||||
|
state. On failure it shows a red ✘ and the exit code; on success it shows
|
||||||
|
only the dim timestamp. When starship is installed and C3 is enabled, the
|
||||||
|
active Docker context is also shown (if non-default):
|
||||||
|
|
||||||
|
✘ 1 myctx Fri Jun 12 00:51:21 2026 ← failed, starship+C3 active
|
||||||
|
✘ 1 Fri Jun 12 00:51:21 2026 ← failed, fallback prompt
|
||||||
|
Fri Jun 12 00:51:21 2026 ← success (no ✘)
|
||||||
|
|
||||||
|
### FZF
|
||||||
|
|
||||||
|
FZF is themed to Catppuccin Mocha via FZF_DEFAULT_OPTS set in
|
||||||
|
integrations/fzf.fish. The colors applied:
|
||||||
|
|
||||||
|
Background: #1E1E2E (base) #313244 (surface0)
|
||||||
|
Foreground: #CDD6F4 (text)
|
||||||
|
Highlights: #F38BA8 (red) #CBA6F7 (mauve) #B4BEFE (lavender)
|
||||||
|
|
||||||
|
To customize, override FZF_DEFAULT_OPTS in local.fish.
|
||||||
|
|
||||||
|
### Catppuccin Mocha Syntax Highlighting
|
||||||
|
|
||||||
|
The Catppuccin Mocha theme ships with this config in themes/ and is applied
|
||||||
|
on first run via `conf.d/first_run.fish`. Colors are stored in fish_variables
|
||||||
|
(universal). To switch variants, install a different theme from themes/:
|
||||||
|
|
||||||
|
fish_config theme save "Catppuccin Latte"
|
||||||
|
|
||||||
|
`---`
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
title: C1 — Command Shadows
|
||||||
|
---
|
||||||
|
|
||||||
|
Disabling `__fish_config_op_aliases` restores standard system behavior for
|
||||||
|
all of these commands.
|
||||||
|
|
||||||
|
Command / Alias Active behavior Disabled fallback
|
||||||
|
───────────────────────────────────────────────────────────────────────────
|
||||||
|
ls eza -l -a --icons --hyperlink system ls
|
||||||
|
cat bat syntax-highlighted; dirs → ls /usr/bin/cat
|
||||||
|
cd zoxide frecency-based navigation fish builtin cd
|
||||||
|
rm moves files to trash (recoverable) command rm (permanent)
|
||||||
|
less $PAGER → ov → less → more → cat system less
|
||||||
|
du duf (disk overview) or dust (dir tree) system du
|
||||||
|
top btop resource monitor system top
|
||||||
|
ping prettyping --nolegend animation system ping
|
||||||
|
ssh kitten ssh in Kitty terminal system ssh
|
||||||
|
rg rg --hyperlink-format=kitty system rg
|
||||||
|
mkdir verbose path-tree display on creation mkdir -p silently
|
||||||
|
bash XDG bashrc + $SHELL reset on exit system bash
|
||||||
|
history timestamps prepended to every entry fish builtin history
|
||||||
|
cp / mv forced -i confirmation prompt cp / mv unmodified
|
||||||
|
wget forced --continue (resume downloads) system wget
|
||||||
|
grep/fgrep/egrep forced --color=auto system grep variants
|
||||||
|
dir / vdir forced --color=auto system dir / vdir
|
||||||
|
help config intercepts "help config" → config-help fish builtin help
|
||||||
|
claude auto-links AGENTS.md as CLAUDE.md before launch command claude
|
||||||
|
edit multi-editor launcher (GUI/term + fallbacks) $EDITOR/nvim/nano/vi
|
||||||
|
|
||||||
|
When C1 is disabled, `rm` uses bare `command rm` with no wrapper — files
|
||||||
|
are permanently deleted, not trashed. There is no intermediate safety net.
|
||||||
|
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
title: C2 — Startup Side-Effects
|
||||||
|
---
|
||||||
|
|
||||||
|
These run automatically without any user action. Disabling
|
||||||
|
`__fish_config_op_autoexec` prevents all of them.
|
||||||
|
|
||||||
|
Component Trigger What it does
|
||||||
|
───────────────────────────────────────────────────────────────────────────
|
||||||
|
Fisher bootstrap First shell only Downloads and installs fisher
|
||||||
|
Fisher update After bootstrap Installs all fish_plugins entries
|
||||||
|
Catppuccin Mocha theme First shell only Applies theme via fish_config
|
||||||
|
paru wrapper Every startup Writes ~/.local/bin/paru wrapper
|
||||||
|
yay wrapper Every startup Writes ~/.local/bin/yay wrapper
|
||||||
|
Python venv activation On every cd Sources .venv/bin/activate.fish
|
||||||
|
WakaTime command hook On every command Reports to WakaTime API
|
||||||
|
Auto-pull fast-forward On entering a repo Background ff-only git pull
|
||||||
|
user-dots symlink Every startup Links $__fish_config_dir/user-dots
|
||||||
|
to $__fish_user_dots_path
|
||||||
|
|
||||||
|
When C2 is disabled: no Fisher install, no theme application, no paru/yay
|
||||||
|
wrapper generation, no automatic venv activation, no WakaTime reporting,
|
||||||
|
no auto-pull (the PWD handler is never registered), and the user-dots
|
||||||
|
convenience symlink is not created. The symlink is git-ignored and only ever
|
||||||
|
managed as a symlink — a real file or directory at that path is left untouched.
|
||||||
|
The symlink has its own opt-out independent of C2: set `__fish_user_dots_symlink`
|
||||||
|
to a falsy value (or toggle "Dots link" off on the config-settings Paths page)
|
||||||
|
to stop generating it and remove any existing link — honoured even when C2 is
|
||||||
|
enabled. Managed by the `__fish_user_dots_link` helper.
|
||||||
|
The first-run completion marker (`__fish_config_first_run_complete`) is still
|
||||||
|
set so the init does not re-run on subsequent shells.
|
||||||
|
|
||||||
|
Python venv activation fires on every directory change. If a directory uses
|
||||||
|
direnv (`.envrc` present), direnv takes priority and auto-venv is skipped for
|
||||||
|
that directory.
|
||||||
|
|
||||||
|
Auto-pull fast-forwards opted-in repositories in the background when you cd
|
||||||
|
into them. The fish-config repo is always covered; other repos are added with
|
||||||
|
the `auto-pull` command (see its entry in the functions reference). It only
|
||||||
|
ever fast-forwards a clean repo whose branch has an upstream — never rebases,
|
||||||
|
merges, or overwrites work — so it is a no-op on dirty trees, divergent
|
||||||
|
branches, or repos without a remote. The handler fires once per repo entry
|
||||||
|
(not on every sub-directory `cd`). The registry is machine-local at
|
||||||
|
`$__fish_user_dots_path/auto-pull.list` (defaults to `~/.config/.user-dots/fish/auto-pull.list`) and is never committed.
|
||||||
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
title: C3 — Key and Environment Overrides
|
||||||
|
---
|
||||||
|
|
||||||
|
These change fundamental shell behavior: how keys work, which pager opens,
|
||||||
|
and what the prompt looks like. Disabling `__fish_config_op_overrides` removes
|
||||||
|
all of them.
|
||||||
|
|
||||||
|
Override What it replaces or sets
|
||||||
|
───────────────────────────────────────────────────────────────────────────
|
||||||
|
Vi mode fish_vi_key_bindings replaces default Emacs mode
|
||||||
|
PATH setup Prepends custom bin directories to the PATH
|
||||||
|
exit → smart_exit exit wrapper that captures scrollback before closing
|
||||||
|
PAGER=ov ov used by git, man, and all $PAGER-aware tools
|
||||||
|
EDITOR=nvim nvim fallback to vi for git commit, etc.
|
||||||
|
GPG_TTY Sets GPG_TTY to current terminal tty
|
||||||
|
MANPAGER=bat pipeline man pages rendered with syntax highlighting
|
||||||
|
CDPATH=. ~/projects ~ bare dir names resolve against ~/projects and ~
|
||||||
|
Bang-bang system ! and $ keys expand history; !^, !*, !-N, !?str?,
|
||||||
|
^old^new abbreviations; six expand_bang_* helpers
|
||||||
|
Autopair ( [ { " ' auto-close to (), [], {}, "", ''
|
||||||
|
Puffer key intercepts . ! $ * keys intercepted for smart expansion
|
||||||
|
Starship prompt fish_prompt replaced by Starship + OSC 133 markers
|
||||||
|
Catppuccin colors 30+ fish_color_* variables set to Mocha palette
|
||||||
|
FZF_DEFAULT_OPTS FZF themed to Catppuccin Mocha colors
|
||||||
|
Right prompt fish_right_prompt: exit code (on failure) + dim timestamp; always rendered; Docker context added when starship+C3 active
|
||||||
|
|
||||||
|
The bang-bang system spans `key_bindings.fish`, `abbr.fish`, `puffer.fish`, and
|
||||||
|
six `expand_bang_*.fish` functions. All are gated together — disabling C3
|
||||||
|
removes the entire bang-expansion system at once.
|
||||||
|
|
||||||
|
When C3 is disabled, `exit` falls back to `builtin exit` with no scrollback
|
||||||
|
capture, no Kitty IPC, and no file I/O on exit. The scrollback capture block
|
||||||
|
is independently controlled by C5 (see below).
|
||||||
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
title: C4 — Terminal and Tool Integration
|
||||||
|
---
|
||||||
|
|
||||||
|
These features couple the shell to specific external tools. Disabling
|
||||||
|
`__fish_config_op_integrations` disables all of them.
|
||||||
|
|
||||||
|
Component Requires
|
||||||
|
───────────────────────────────────────────────────────────────────────────
|
||||||
|
≈ 60 Kitty/WezTerm abbrs Active Kitty or WezTerm session
|
||||||
|
(:w, :wv, :wh, :t, etc.)
|
||||||
|
Done desktop notifications Graphical desktop with a notification daemon
|
||||||
|
spwin Kitty or WezTerm
|
||||||
|
tab Kitty, WezTerm, or Konsole
|
||||||
|
split Kitty or WezTerm
|
||||||
|
hist fzf + wl-copy (Wayland clipboard)
|
||||||
|
logs fzf + ov; reads from ~/.terminal_history/
|
||||||
|
upgrade paru or yay (Arch Linux only)
|
||||||
|
WakaTime hook wakatime CLI and a configured API key
|
||||||
|
|
||||||
|
Disabled integration commands (`spwin`, `tab`, `split`, `hist`, `logs`, `upgrade`) print
|
||||||
|
a colored error to stderr naming the variable that disabled them rather than
|
||||||
|
silently failing.
|
||||||
|
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
---
|
||||||
|
title: C5 — Logging and Capture
|
||||||
|
---
|
||||||
|
|
||||||
|
Five components capture shell output to disk. Unlike every other category,
|
||||||
|
C5 is opt-in: it stays off until `__fish_config_op_logging` is set to an
|
||||||
|
explicit truthy value, and a truthy master switch does not enable it. While
|
||||||
|
it is off, all capture is skipped and the logging wrappers are removed.
|
||||||
|
|
||||||
|
CAUTION: This configuration is capable of silently recording terminal output and secrets directly to disk. See below for details on how this capture mechanism works, where files are stored, and how to manage its state.
|
||||||
|
|
||||||
|
# Turn it on (persistently, in every shell):
|
||||||
|
set -U __fish_config_op_logging on
|
||||||
|
|
||||||
|
# Turn it back off:
|
||||||
|
set -U __fish_config_op_logging off # or: set -Ue __fish_config_op_logging
|
||||||
|
|
||||||
|
Component What it captures
|
||||||
|
───────────────────────────────────────────────────────────────────────────
|
||||||
|
Scrollback capture Terminal session output saved to:
|
||||||
|
`~/.terminal_history/scrollback_YYYY-MM-DD_HH-MM-SS.log`
|
||||||
|
tmux pane capture Continuous pane stream via pipe-pane, saved to:
|
||||||
|
`~/.terminal_history/tmux_<session>-w<win>-p<pane>_YYYY-MM-DD_HH-MM-SS.log`
|
||||||
|
zellij pane capture Pane scrollback snapshot on shell exit, saved to:
|
||||||
|
`~/.terminal_history/zellij_<session>-p<pane>_YYYY-MM-DD_HH-MM-SS.log`
|
||||||
|
paru wrapper All paru/AUR output captured to:
|
||||||
|
`~/.terminal_history/paru_YYYY-MM-DD_HH-MM-SS.log`
|
||||||
|
yay wrapper All yay/AUR output captured to:
|
||||||
|
`~/.terminal_history/yay_YYYY-MM-DD_HH-MM-SS.log`
|
||||||
|
Kitty watcher `watcher.py` captures scrollback when Kitty closes
|
||||||
|
|
||||||
|
NOTE: **Turning off logging does not delete any existing logs.**
|
||||||
|
They remain in `$SCROLLBACK_HISTORY_DIR` (defaults to: `~/.terminal_history/`)
|
||||||
|
until you remove them manually.
|
||||||
|
|
||||||
|
The tmux capture starts automatically when fish launches inside any tmux
|
||||||
|
pane (`$TMUX` is set). It uses tmux's native pipe-pane to stream all pane
|
||||||
|
output directly to disk without an intermediate process. Each fish shell
|
||||||
|
session gets its own log file; a new log is created on each shell start
|
||||||
|
(including exec fish and new splits). Before each new log, the oldest
|
||||||
|
`tmux_*.log` files are pruned (by modification time) to keep the total within
|
||||||
|
`SCROLLBACK_HISTORY_MAX_FILES`, matching the paru/yay wrapper behaviour.
|
||||||
|
|
||||||
|
The zellij capture works differently: Zellij has no live output-streaming
|
||||||
|
facility like pipe-pane, so the log is taken as a one-shot snapshot when the
|
||||||
|
shell exits, via `zellij action dump-screen --full --ansi` (the `--ansi` flag
|
||||||
|
preserves color). The dump is captured on the fish process's stdout and
|
||||||
|
written to the log file by fish itself (not via `--path`, which would make the
|
||||||
|
zellij server write the file). A fish_exit handler (registered whenever
|
||||||
|
`$ZELLIJ` is set) writes the pane's full scrollback and then prunes old
|
||||||
|
`zellij_*.log` files the same way. Because the capture happens at exit, toggling
|
||||||
|
`__fish_config_op_logging` takes effect on the next exit with no restart or
|
||||||
|
sentinel coordination needed — the C5 guard is re-checked when the handler
|
||||||
|
fires.
|
||||||
|
|
||||||
|
LIMITATION — zellij capture only fires on a clean shell exit (typing `exit`,
|
||||||
|
Ctrl-D, or a logout), because that is when the fish_exit handler runs. It does
|
||||||
|
NOT capture when you close a pane or quit zellij through zellij itself:
|
||||||
|
|
||||||
|
- Closing a pane signals the shell and tears the pane down concurrently, so
|
||||||
|
even if the handler runs, `dump-screen` may find the pane buffer already
|
||||||
|
gone.
|
||||||
|
- Quitting zellij kills the zellij server, and `dump-screen` needs a live
|
||||||
|
server to read from — there is nothing left to snapshot.
|
||||||
|
|
||||||
|
This is a structural difference from tmux, NOT a bug. tmux streams pane output
|
||||||
|
to disk continuously via pipe-pane, so whatever was printed is already saved
|
||||||
|
no matter how the pane dies. Zellij can only snapshot, and the only reliable
|
||||||
|
snapshot point from the shell is a clean exit. To guarantee a zellij pane is
|
||||||
|
logged, end the session with `exit` or Ctrl-D rather than zellij's close-pane
|
||||||
|
or quit actions.
|
||||||
|
|
||||||
|
The Kitty watcher is managed by the kitty-logging command: it symlinks the
|
||||||
|
watcher (`fish-config-watcher.py`) into the Kitty config directory and wires it
|
||||||
|
into `kitty.conf` via a managed block. Inside Kitty, a non-blocking
|
||||||
|
per-session reminder points first-time users at `kitty-logging install` until
|
||||||
|
they install or run `kitty-logging dismiss`; the reminder is itself gated on
|
||||||
|
C5, so it stays silent until you enable logging. Install affects new Kitty
|
||||||
|
windows only; runtime disable is still handled by the `.logging_disabled`
|
||||||
|
sentinel.
|
||||||
|
|
||||||
|
Logging coordination via sentinel file
|
||||||
|
|
||||||
|
C5 uses a sentinel file to synchronize state between the shell and
|
||||||
|
out-of-process components (the Kitty watcher and all running shells):
|
||||||
|
|
||||||
|
~/.config/fish/.logging_disabled
|
||||||
|
|
||||||
|
Because C5 is off by default, the sentinel is present on a fresh install —
|
||||||
|
the startup sync in `conf.d/logging-events.fish` reconciles it on every shell
|
||||||
|
start, so it appears without any action on your part.
|
||||||
|
|
||||||
|
Disabling `__fish_config_op_logging` (or leaving it unset):
|
||||||
|
1. Creates the sentinel immediately in every open shell.
|
||||||
|
2. Removes `~/.local/bin/paru` and `~/.local/bin/yay` logging wrappers;
|
||||||
|
bare `/usr/bin/paru` and `/usr/bin/yay` are used instead.
|
||||||
|
3. Kitty's `watcher.py` reads the sentinel on each save attempt and
|
||||||
|
skips capture — no Kitty restart required.
|
||||||
|
4. smart_exit stops saving scrollback logs.
|
||||||
|
5. Stops `tmux pipe-pane` capture in every open fish shell inside tmux.
|
||||||
|
|
||||||
|
Enabling `__fish_config_op_logging`:
|
||||||
|
1. Removes the sentinel in every open shell.
|
||||||
|
2. Regenerates paru/yay logging wrappers in `~/.local/bin/`.
|
||||||
|
3. Kitty watcher resumes capture on the next session exit.
|
||||||
|
4. Restarts tmux pipe-pane capture in every open fish shell inside tmux.
|
||||||
|
|
||||||
|
Changes propagate to all running shells through an event handler that fires
|
||||||
|
whenever `__fish_config_op_logging` changes — no shell restart needed.
|
||||||
|
|
||||||
|
Note: C3 and C5 compose independently. C3 controls whether the smart_exit
|
||||||
|
wrapper is active at all; C5 controls only the scrollback-capture block
|
||||||
|
inside it. With C3 disabled, exit is plain builtin exit regardless of C5.
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
title: C6 — Greeting and First-Run UI
|
||||||
|
---
|
||||||
|
|
||||||
|
Component What it shows
|
||||||
|
───────────────────────────────────────────────────────────────────────────
|
||||||
|
First-run welcome banner One-time message on first interactive session
|
||||||
|
fish_greeting override Empty function defined late in config.fish to
|
||||||
|
suppress distro greetings (e.g. CachyOS sets
|
||||||
|
fish_greeting to fastfetch by default)
|
||||||
|
|
||||||
|
When C6 is disabled, no greeting is printed by this config. Any greeting
|
||||||
|
set by the distro or other configs runs normally — this config simply does
|
||||||
|
not override it.
|
||||||
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
title: Components Reference
|
||||||
|
manTitle: 8. COMPONENTS REFERENCE
|
||||||
|
sidebar:
|
||||||
|
order: 12
|
||||||
|
helpKeywords:
|
||||||
|
- componentsreference
|
||||||
|
---
|
||||||
|
The following tables detail every component in each category. Use this
|
||||||
|
reference to understand exactly which behaviors change when you toggle a
|
||||||
|
category variable.
|
||||||
|
|
||||||
|
Category Description
|
||||||
|
──────────────────────────────────────────────────────────────────────────
|
||||||
|
C1 [Command Shadows](/08-components-reference/01-c1-command-shadows/) — Wraps destructive commands (`rm`, `cp`) to be safe by default
|
||||||
|
C2 [Startup Side-Effects](/08-components-reference/02-c2-startup-side-effects/) — Bootstraps Fisher, generates wrappers, auto-activates venvs
|
||||||
|
C3 [Overrides](/08-components-reference/03-c3-key-and-environment-overrides/) — Overrides `cd`, sets Vi mode, binds `<CR>` to `smart_enter`
|
||||||
|
C4 [Integrations](/08-components-reference/04-c4-terminal-and-tool-integration/) — Kitty/Wezterm integrations, starship hooks, fzf theme
|
||||||
|
C5 [Logging and Capture](/08-components-reference/05-c5-logging-and-capture/) — Session logs, command duration
|
||||||
|
C6 [Greeting & First-Run UI](/08-components-reference/06-c6-greeting-and-first-run-ui/) — Custom startup banner
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
---
|
||||||
|
title: Fisher Plugins
|
||||||
|
manTitle: 9. FISHER PLUGINS
|
||||||
|
sidebar:
|
||||||
|
order: 13
|
||||||
|
helpKeywords:
|
||||||
|
- plugins
|
||||||
|
- fisher
|
||||||
|
---
|
||||||
|
|
||||||
|
Fisher is bootstrapped automatically on the **first interactive session** via
|
||||||
|
`conf.d/first_run.fish`. This also applies the Catppuccin Mocha theme and
|
||||||
|
prints a one-time welcome message (gated by `__fish_config_op_greeting`; set
|
||||||
|
it to 0 to suppress). Subsequent sessions skip all first-run logic with zero
|
||||||
|
overhead.
|
||||||
|
|
||||||
|
To re-trigger first-run initialization (e.g., after a fresh install or for
|
||||||
|
testing), run:
|
||||||
|
|
||||||
|
set -Ue __fish_config_first_run_complete
|
||||||
|
|
||||||
|
Then open a new shell.
|
||||||
|
|
||||||
|
## Fisher-Managed Plugins
|
||||||
|
|
||||||
|
The following plugins are fully managed by Fisher. Their files are installed
|
||||||
|
into the repo directory by Fisher and are listed in `.gitignore` — do not
|
||||||
|
commit them. Fisher installs and updates them automatically.
|
||||||
|
|
||||||
|
- `jorgebucaran/fisher` — Plugin manager itself
|
||||||
|
- `meaningful-ooo/sponge` — Remove failed commands from history
|
||||||
|
|
||||||
|
## Sponge History Filtering
|
||||||
|
|
||||||
|
Sponge removes failed commands from history and, via conf.d/sponge_privacy.fish,
|
||||||
|
also filters privacy-sensitive commands through three layers:
|
||||||
|
|
||||||
|
Layer 1 — Static patterns (universal, persistent across sessions):
|
||||||
|
Commands matching any of these structural signatures are never recorded:
|
||||||
|
|
||||||
|
- `--password` / `--token` / `--passphrase` / `--api-key` flags with values
|
||||||
|
- Inline env assignments: `GITHUB_TOKEN=xxx`, `MY_API_KEY=abc`
|
||||||
|
- Fish set with sensitive names: `set -gx GITHUB_TOKEN xxx`
|
||||||
|
- URLs with embedded credentials: `https://user:pass@host`
|
||||||
|
- HTTP Authorization headers: `curl -H "Authorization: ..."`
|
||||||
|
- Basic auth flags: `curl -u user:pass`
|
||||||
|
- `sshpass`, `docker login -p`, `openssl -passin/-passout`
|
||||||
|
|
||||||
|
Layer 2 — Dynamic secret values (session globals, refreshed each login):
|
||||||
|
On the first prompt, after secrets.fish has loaded, the literal values of
|
||||||
|
all exported variables whose names suggest credentials (TOKEN, PASSWORD,
|
||||||
|
SECRET, API_KEY, etc.) are collected, regex-escaped, and added as a
|
||||||
|
session-scoped overlay. Because globals shadow universals in Fish, the
|
||||||
|
combined list is what sponge sees. Rotating a token takes effect on the
|
||||||
|
next login automatically.
|
||||||
|
|
||||||
|
Layer 3 — Per-command filter (sponge_filter_secrets):
|
||||||
|
Catches credentials in variables exported after login, such as tokens
|
||||||
|
sourced from a project .env file mid-session.
|
||||||
|
|
||||||
|
To add your own persistent patterns:
|
||||||
|
|
||||||
|
set -U -a sponge_regex_patterns 'your-regex-here'
|
||||||
|
|
||||||
|
To mark additional variable NAMES as credential-bearing (so Layer 2 scrubs
|
||||||
|
their values), add name tokens — via `config-settings` → Sponge, or directly:
|
||||||
|
|
||||||
|
set -U -a __fish_sponge_extra_sensitive ACME_API VAULT_PW
|
||||||
|
|
||||||
|
Tokens are folded into the Layer 2 name match case-insensitively as substrings,
|
||||||
|
so ACME_API also covers ACME_API_KEY. (The match uses `--entire` to return the
|
||||||
|
full variable name, so partial-name tokens dereference the right value.)
|
||||||
|
|
||||||
|
The `config-settings` Sponge page also surfaces sponge's own tuning variables —
|
||||||
|
sponge_delay, sponge_successful_exit_codes, sponge_purge_only_on_exit, and
|
||||||
|
sponge_allow_previously_successful — so they can be changed without typing
|
||||||
|
variable names.
|
||||||
|
|
||||||
|
## Bundled Plugin Functionality
|
||||||
|
|
||||||
|
The remaining plugin functionality is bundled directly with this config rather
|
||||||
|
than managed through Fisher. The bundled versions include customizations for
|
||||||
|
Fish 4.x compatibility and improved behavior that differ from their upstream
|
||||||
|
releases. Installing them through Fisher would overwrite these customizations.
|
||||||
|
|
||||||
|
Bundled components and their upstream origins:
|
||||||
|
|
||||||
|
- `catppuccin/fish` → `themes/` + `conf.d/theme.fish`
|
||||||
|
- `PatrickF1/fzf.fish` → `functions/_fzf_*.fish` + `conf.d/fzf.fish`
|
||||||
|
- `franciscolourenco/done` → `conf.d/done.fish`
|
||||||
|
- `jorgebucaran/autopair.fish` → `functions/_autopair_*.fish` + `conf.d/autopair.fish`
|
||||||
|
- `nickeb96/puffer-fish` → `functions/_puffer_fish_*.fish` + `conf.d/puffer.fish`
|
||||||
|
|
||||||
|
Do not run `fisher install` for these — it will overwrite the customized
|
||||||
|
versions. To update their behavior, edit the relevant bundled files directly.
|
||||||
|
|
||||||
|
## fish_plugins Manifest
|
||||||
|
|
||||||
|
The `fish_plugins` file at the config root:
|
||||||
|
|
||||||
|
- `jorgebucaran/fisher` — Plugin manager itself
|
||||||
|
- `meaningful-ooo/sponge` — Remove failed commands from history
|
||||||
|
|
||||||
|
To update all Fisher-managed plugins, run `fisher update` or `fish-deps
|
||||||
|
update` which calls it as its first step.
|
||||||
|
|
||||||
|
---
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
title: Installation
|
||||||
|
manTitle: 10. INSTALLATION
|
||||||
|
sidebar:
|
||||||
|
order: 14
|
||||||
|
helpKeywords:
|
||||||
|
- installation
|
||||||
|
- install
|
||||||
|
---
|
||||||
|
|
||||||
|
This configuration is managed as a git repository. To deploy on a new machine:
|
||||||
|
|
||||||
|
mv ~/.config/fish ~/.config/fish.bak # back up any existing config
|
||||||
|
git clone https://git.rootiest.dev/rootiest/fish-config.git ~/.config/fish
|
||||||
|
|
||||||
|
Then open a new Fish shell. Fisher installs automatically on first launch
|
||||||
|
and the Catppuccin Mocha theme is applied. All other plugin functionality is
|
||||||
|
bundled directly with this config and requires no additional installation.
|
||||||
|
|
||||||
|
## Return Sentinel
|
||||||
|
|
||||||
|
`config.fish` ends with a return sentinel guard. Any lines appended after it by
|
||||||
|
a tool's setup command (`starship init fish | source`, `zoxide init fish | source`,
|
||||||
|
etc.) will have no effect. All integrations are managed via `conf.d/` files.
|
||||||
|
|
||||||
|
If a new tool's shell integration appears to do nothing, check whether its
|
||||||
|
setup command appended an init line below the sentinel and create a dedicated
|
||||||
|
`conf.d/<tool>.fish` instead.
|
||||||
|
|
||||||
|
## Updating
|
||||||
|
|
||||||
|
Pull the latest changes from the upstream repository without needing a
|
||||||
|
configured git remote:
|
||||||
|
|
||||||
|
- `config-update` — Fetch and apply the latest commits from upstream
|
||||||
|
- `config-update --dry-run` — Preview available changes without applying them
|
||||||
|
- `config-update --force` — Stash local changes, pull, then restore the stash
|
||||||
|
|
||||||
|
All git output is suppressed. Run `exec fish` after a successful update to reload.
|
||||||
|
|
||||||
|
---
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
---
|
||||||
|
title: Personalization
|
||||||
|
manTitle: 11. PERSONALIZATION
|
||||||
|
sidebar:
|
||||||
|
order: 15
|
||||||
|
helpKeywords:
|
||||||
|
- personalization
|
||||||
|
- personalize
|
||||||
|
---
|
||||||
|
|
||||||
|
Sensitive credentials and machine-specific settings are kept out of version
|
||||||
|
control in a private directory. The path defaults to
|
||||||
|
`~/.config/.user-dots/fish/` but can be overridden:
|
||||||
|
|
||||||
|
set -U __fish_user_dots_path /path/to/your/dots/fish
|
||||||
|
|
||||||
|
Or use the interactive TUI — run `config-settings` and navigate to the
|
||||||
|
"Dots Path" row (last row). Press Enter to type a new path, or ← / h to
|
||||||
|
reset to the default.
|
||||||
|
|
||||||
|
config.fish sources local.fish from that directory on every interactive
|
||||||
|
session. local.fish is responsible for sourcing its own secrets.fish:
|
||||||
|
|
||||||
|
$__fish_user_dots_path/
|
||||||
|
├── secrets.fish API keys, tokens, passwords, personal identifiers
|
||||||
|
└── local.fish Machine-specific paths, env vars, and sourcing secrets
|
||||||
|
|
||||||
|
fish_variables (auto-managed by fish) is excluded from this repo via
|
||||||
|
.gitignore. Do not commit it.
|
||||||
|
|
||||||
|
## secrets.fish
|
||||||
|
|
||||||
|
Store anything you would not commit to a public repo: API keys, auth tokens,
|
||||||
|
passwords, and personal identifiers.
|
||||||
|
|
||||||
|
# secrets.fish
|
||||||
|
set -gx MY_NAME "Your Name"
|
||||||
|
set -gx MY_EMAIL "you@example.com"
|
||||||
|
set -gx GPG_RECIPIENT "you@example.com"
|
||||||
|
set -gx GITHUB_TOKEN ghp_yourTokenHere
|
||||||
|
set -gx OPENAI_API_KEY sk-proj-yourKeyHere
|
||||||
|
set -gx GITEA_TOKEN yourGiteaTokenHere
|
||||||
|
set -gx GITEA_CHOSEN_LOGIN your.gitea.instance
|
||||||
|
set -gx KOPIA_PASSWORD yourKopiaPassword
|
||||||
|
|
||||||
|
## local.fish
|
||||||
|
|
||||||
|
Store paths and variables specific to one machine — things that would be
|
||||||
|
wrong on any other system.
|
||||||
|
|
||||||
|
# CDPATH — directories searched by cd
|
||||||
|
set -gx CDPATH . /home/youruser/projects /home/youruser
|
||||||
|
|
||||||
|
# Path to your shared .gitignore boilerplate
|
||||||
|
set -gx GITIGNORE_BOILERPLATE ~/.config/git/gitignore_boilerplate
|
||||||
|
|
||||||
|
# SSH shortcuts
|
||||||
|
abbr -a sshr 'ssh you@your-server.local'
|
||||||
|
abbr -a sshw 'ssh you@work-server.example.com'
|
||||||
|
|
||||||
|
# Docker context shortcuts
|
||||||
|
abbr -a dcr 'docker context use my-remote-server'
|
||||||
|
abbr -a dcw 'docker context use work-server'
|
||||||
|
|
||||||
|
local.fish is sourced at the end of config.fish with an existence check so
|
||||||
|
the public config works cleanly on any machine without the private repo.
|
||||||
|
local.fish in turn sources secrets.fish when it exists.
|
||||||
|
|
||||||
|
---
|
||||||
@@ -0,0 +1,242 @@
|
|||||||
|
---
|
||||||
|
title: Troubleshooting
|
||||||
|
manTitle: 12. TROUBLESHOOTING
|
||||||
|
sidebar:
|
||||||
|
order: 16
|
||||||
|
helpKeywords:
|
||||||
|
- troubleshooting
|
||||||
|
- troubleshoot
|
||||||
|
- faq
|
||||||
|
- help
|
||||||
|
- uninstall
|
||||||
|
- revert
|
||||||
|
---
|
||||||
|
|
||||||
|
This section covers common issues, their solutions, and how to safely revert changes or uninstall the configuration entirely.
|
||||||
|
|
||||||
|
## Uninstalling and Reverting to Backup
|
||||||
|
|
||||||
|
The installation step backs up any existing config to `~/.config/fish.bak`.
|
||||||
|
To revert:
|
||||||
|
|
||||||
|
rm -rf ~/.config/fish
|
||||||
|
mv ~/.config/fish.bak ~/.config/fish
|
||||||
|
|
||||||
|
If no backup exists, remove the directory and let Fish regenerate a default
|
||||||
|
config on next launch:
|
||||||
|
|
||||||
|
rm -rf ~/.config/fish
|
||||||
|
fish -c 'fish_config theme choose "Fish default"'
|
||||||
|
|
||||||
|
Clean up files generated outside the config directory:
|
||||||
|
|
||||||
|
rm -f ~/.local/bin/paru ~/.local/bin/yay # AUR log wrappers
|
||||||
|
rm -f ~/.local/share/man/man1/fish-config.1 # man page symlink
|
||||||
|
rm -f ~/.config/fish/.logging_disabled # C5 sentinel
|
||||||
|
|
||||||
|
Erase universal variables set by this config:
|
||||||
|
|
||||||
|
for v in (set -Un | string match '__fish_config*')
|
||||||
|
set -Ue $v
|
||||||
|
end
|
||||||
|
for v in __done_min_cmd_duration __done_notification_urgency_level
|
||||||
|
set -Ue $v
|
||||||
|
end
|
||||||
|
for v in (set -Un | string match 'sponge_*')
|
||||||
|
set -Ue $v
|
||||||
|
end
|
||||||
|
|
||||||
|
The `~/.terminal_history/` log directory contains your session logs. Remove
|
||||||
|
it only if you do not want to keep them.
|
||||||
|
|
||||||
|
## Fish Version Requirement
|
||||||
|
|
||||||
|
This config requires Fish 4.x or newer. Check your version:
|
||||||
|
|
||||||
|
fish --version
|
||||||
|
|
||||||
|
Run `fish-deps` to see a status report — an outdated Fish shows ⚠ with an
|
||||||
|
upgrade message.
|
||||||
|
|
||||||
|
Upgrading Fish by distribution:
|
||||||
|
|
||||||
|
# Arch / AUR
|
||||||
|
pacman -S fish # or paru -S fish
|
||||||
|
|
||||||
|
# Ubuntu / Debian (PPA)
|
||||||
|
sudo apt-add-repository ppa:fish-shell/release-4
|
||||||
|
sudo apt update && sudo apt install fish
|
||||||
|
|
||||||
|
# Fedora
|
||||||
|
sudo dnf install fish
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
brew install fish
|
||||||
|
|
||||||
|
For other systems or building from source, see https://fishshell.com.
|
||||||
|
|
||||||
|
## Enable or Disable Session Logging
|
||||||
|
|
||||||
|
Session logging is opt-in: it is off until you turn it on. To enable all
|
||||||
|
logging and capture (scrollback, tmux/zellij pane logs, AUR helper wrappers,
|
||||||
|
Kitty watcher):
|
||||||
|
|
||||||
|
set -U __fish_config_op_logging on
|
||||||
|
|
||||||
|
Or toggle it interactively: run `config-settings` and flip the Logging row.
|
||||||
|
|
||||||
|
Disable it again — either an explicit falsy value or erasing the variable
|
||||||
|
returns you to the default off state:
|
||||||
|
|
||||||
|
set -U __fish_config_op_logging off
|
||||||
|
set -Ue __fish_config_op_logging
|
||||||
|
|
||||||
|
This takes effect immediately in all running shells — no restart needed. The
|
||||||
|
sentinel file, wrapper removal, and pipe-pane teardown happen automatically.
|
||||||
|
|
||||||
|
See [C5 — Logging and Capture](/08-components-reference/05-c5-logging-and-capture/) for the full component breakdown.
|
||||||
|
|
||||||
|
## Change or Disable the Greeting
|
||||||
|
|
||||||
|
This config suppresses the distro greeting (e.g. CachyOS fastfetch) by
|
||||||
|
default. To let the distro greeting through:
|
||||||
|
|
||||||
|
set -U __fish_config_op_greeting off
|
||||||
|
|
||||||
|
To set a custom greeting, define fish_greeting in your local.fish:
|
||||||
|
|
||||||
|
# in $__fish_user_dots_path/local.fish
|
||||||
|
function fish_greeting
|
||||||
|
echo "Hello, world!"
|
||||||
|
end
|
||||||
|
|
||||||
|
The first-run welcome banner runs exactly once. To re-trigger it (e.g. for
|
||||||
|
testing):
|
||||||
|
|
||||||
|
set -Ue __fish_config_first_run_complete
|
||||||
|
|
||||||
|
See [C6 — Greeting and First-Run UI](/08-components-reference/06-c6-greeting-and-first-run-ui/) for details.
|
||||||
|
|
||||||
|
## Secrets and Machine-Local Configuration
|
||||||
|
|
||||||
|
Machine-specific config goes in `$__fish_user_dots_path/local.fish` (defaults
|
||||||
|
to `~/.config/.user-dots/fish/local.fish`). Secrets go in `secrets.fish` in
|
||||||
|
the same directory.
|
||||||
|
|
||||||
|
If local.fish is not loading, verify the path:
|
||||||
|
|
||||||
|
echo $__fish_user_dots_path
|
||||||
|
test -f "$__fish_user_dots_path/local.fish"; and echo exists; or echo missing
|
||||||
|
|
||||||
|
Change the path via variable or TUI:
|
||||||
|
|
||||||
|
set -U __fish_user_dots_path /new/path/to/dots/fish
|
||||||
|
|
||||||
|
Or run `config-settings`, navigate to the Paths page, and edit "Dots path".
|
||||||
|
|
||||||
|
The `user-dots` convenience symlink in the config directory tracks this path.
|
||||||
|
Disable it with:
|
||||||
|
|
||||||
|
set -U __fish_user_dots_symlink false
|
||||||
|
|
||||||
|
See [Personalization](/11-personalization/) for the full `local.fish` / `secrets.fish`
|
||||||
|
layout.
|
||||||
|
|
||||||
|
## Tool Init Does Nothing (Return Sentinel)
|
||||||
|
|
||||||
|
Symptom: you ran a tool's setup command (e.g.
|
||||||
|
`starship init fish >> ~/.config/fish/config.fish`) and nothing changed.
|
||||||
|
|
||||||
|
Cause: `config.fish` ends with a `return` guard. Any lines appended after it
|
||||||
|
are never executed.
|
||||||
|
|
||||||
|
Fix: create a dedicated `conf.d/` file instead of appending to `config.fish`:
|
||||||
|
|
||||||
|
# ~/.config/fish/conf.d/mytool.fish
|
||||||
|
mytool init fish | source
|
||||||
|
|
||||||
|
All existing integrations (starship, zoxide, direnv) already have `conf.d/`
|
||||||
|
files. See [Return Sentinel](/10-installation/#return-sentinel) for background.
|
||||||
|
|
||||||
|
## Missing Dependencies
|
||||||
|
|
||||||
|
Run `fish-deps` (defaults to `fish-deps status`) to see what is installed
|
||||||
|
and what is missing. Common symptoms and their missing tools:
|
||||||
|
|
||||||
|
Symptom Missing tool
|
||||||
|
─────────────────────────────────────────────────────
|
||||||
|
ls output has no icons or colors eza (or lsd)
|
||||||
|
cd does not remember directories zoxide
|
||||||
|
cat shows no syntax highlighting bat
|
||||||
|
fzf keybindings do nothing fzf
|
||||||
|
Starship prompt not appearing starship
|
||||||
|
|
||||||
|
Install missing dependencies interactively:
|
||||||
|
|
||||||
|
fish-deps install
|
||||||
|
|
||||||
|
Or install everything missing and update what is installed:
|
||||||
|
|
||||||
|
fish-deps sync
|
||||||
|
|
||||||
|
See [Dependency Catalog](/06-dependency-catalog/) for the full list grouped by tier
|
||||||
|
(required, integrations, recommended).
|
||||||
|
|
||||||
|
## Vi Mode Keybindings
|
||||||
|
|
||||||
|
This config enables Vi mode by default (via C3 overrides), replacing the
|
||||||
|
standard Emacs-style bindings. If Vi mode interferes with your workflow,
|
||||||
|
override it in `local.fish` (See [Personalization](/11-personalization/)):
|
||||||
|
|
||||||
|
# $__fish_user_dots_path/local.fish
|
||||||
|
fish_default_key_bindings
|
||||||
|
|
||||||
|
This restores Emacs-style bindings without disabling the rest of C3
|
||||||
|
(bang-bang, autopair, starship prompt, pager settings, etc.).
|
||||||
|
|
||||||
|
To disable the entire C3 category (Vi mode and all other key/environment
|
||||||
|
overrides):
|
||||||
|
|
||||||
|
set -U __fish_config_op_overrides off
|
||||||
|
|
||||||
|
See [C3 — Key and Environment Overrides](/08-components-reference/03-c3-key-and-environment-overrides/) for the full list of
|
||||||
|
what C3 controls.
|
||||||
|
|
||||||
|
## What's with the C1-C6 stuff?
|
||||||
|
|
||||||
|
This configuration groups its opinionated behaviors into six categories (C1–C6), allowing you to selectively disable features that conflict with your workflow. The **C**ategory numbers are used as shorthand when referencing these. Disabling all of them leaves you with a "Minimal Mode" shell that only manages basic features like `XDG` variables, and your `local.fish` overrides.
|
||||||
|
|
||||||
|
Category Description
|
||||||
|
──────────────────────────────────────────────────────────────────────────
|
||||||
|
C1 [Command Shadows](/08-components-reference/01-c1-command-shadows/) — Wraps destructive commands (`rm`, `cp`) to be safe by default
|
||||||
|
C2 [Startup Side-Effects](/08-components-reference/02-c2-startup-side-effects/) — Bootstraps Fisher, generates wrappers, auto-activates venvs
|
||||||
|
C3 [Overrides](/08-components-reference/03-c3-key-and-environment-overrides/) — Overrides `cd`, sets Vi mode, binds `<CR>` to `smart_enter`
|
||||||
|
C4 [Integrations](/08-components-reference/04-c4-terminal-and-tool-integration/) — Kitty/Wezterm integrations, starship hooks, fzf theme
|
||||||
|
C5 [Logging and Capture](/08-components-reference/05-c5-logging-and-capture/) — Session logs, command duration
|
||||||
|
C6 [Greeting & First-Run UI](/08-components-reference/06-c6-greeting-and-first-run-ui/) — Custom startup banner
|
||||||
|
|
||||||
|
Disable all opinionated features at once (Minimal Mode):
|
||||||
|
|
||||||
|
set -U __fish_config_opinionated 0
|
||||||
|
|
||||||
|
Disable a single category:
|
||||||
|
|
||||||
|
set -U __fish_config_op_aliases off # C1
|
||||||
|
set -U __fish_config_op_autoexec off # C2
|
||||||
|
set -U __fish_config_op_overrides off # C3
|
||||||
|
set -U __fish_config_op_integrations off # C4
|
||||||
|
set -U __fish_config_op_logging off # C5 (already off by default)
|
||||||
|
set -U __fish_config_op_greeting off # C6
|
||||||
|
|
||||||
|
Keep one category active under a master disable:
|
||||||
|
|
||||||
|
set -U __fish_config_opinionated 0
|
||||||
|
set -U __fish_config_op_aliases 1 # only C1 stays on
|
||||||
|
|
||||||
|
Re-enable everything:
|
||||||
|
|
||||||
|
set -Ue __fish_config_opinionated
|
||||||
|
|
||||||
|
For an interactive alternative to setting these variables by hand, run `config-settings`.
|
||||||
|
|
||||||
|
---
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
---
|
||||||
|
title: Viewing This Manual
|
||||||
|
manTitle: 13. VIEWING THIS MANUAL
|
||||||
|
sidebar:
|
||||||
|
order: 17
|
||||||
|
helpKeywords:
|
||||||
|
- viewing
|
||||||
|
- manual
|
||||||
|
---
|
||||||
|
|
||||||
|
There are four ways to read this manual.
|
||||||
|
|
||||||
|
## The documentation website
|
||||||
|
|
||||||
|
help config --html
|
||||||
|
|
||||||
|
Opens https://fish.rootiest.fyi/ in the default browser — the
|
||||||
|
Starlight-powered site built from `docs/manual/**` on every push to `main`.
|
||||||
|
It has a section sidebar and full-text search. Deep links to a specific
|
||||||
|
section aren't supported from the command line; once the site opens, use
|
||||||
|
its search box to jump straight to what you need.
|
||||||
|
|
||||||
|
## As a man page
|
||||||
|
|
||||||
|
help config --man
|
||||||
|
help config pkg --man
|
||||||
|
|
||||||
|
Opens the compiled docs/fish-config.1 directly via man -l, bypassing
|
||||||
|
the pager fallback chain. If a section keyword is given, the pager opens
|
||||||
|
at the nearest matching heading. The symlink is created once on first
|
||||||
|
run (like an install step) and MANPATH is set each session, enabling
|
||||||
|
the standard invocation:
|
||||||
|
|
||||||
|
man fish-config
|
||||||
|
|
||||||
|
NOTE: fish-config (hyphen) is this config's man page. fish_config
|
||||||
|
(underscore) is fish's built-in browser-based configuration tool —
|
||||||
|
a completely separate command. Do not mix them up.
|
||||||
|
|
||||||
|
## In the terminal
|
||||||
|
|
||||||
|
help config
|
||||||
|
help config keybindings
|
||||||
|
|
||||||
|
Without a pager available beyond the basics, `help config [SECTION]` opens
|
||||||
|
the Markdown manual in the best available viewer, falling back through:
|
||||||
|
|
||||||
|
1. ov + bat section navigation + syntax highlighting (best)
|
||||||
|
2. ov alone section navigation, raw Markdown
|
||||||
|
3. bat alone syntax highlighting, use / to search
|
||||||
|
4. man -l pre-compiled man page (if available)
|
||||||
|
5. less plain text with line-jump
|
||||||
|
6. cat plain output
|
||||||
|
|
||||||
|
With ov, the Markdown renders with syntax highlighting and section-based
|
||||||
|
navigation:
|
||||||
|
|
||||||
|
Space next section
|
||||||
|
^ previous section
|
||||||
|
Alt+u toggle section list sidebar
|
||||||
|
/ search forward
|
||||||
|
n / N next / previous search match
|
||||||
|
g go to line number
|
||||||
|
j interactive jump target (line, %, or 'section')
|
||||||
|
q quit
|
||||||
|
|
||||||
|
If SECTION is given, the pager opens at the first heading that matches the
|
||||||
|
keyword (case-insensitive; checks `docs/fish-config.index` aliases first,
|
||||||
|
then falls back to a normalized heading scan):
|
||||||
|
|
||||||
|
help config keybindings
|
||||||
|
help config abbreviations
|
||||||
|
help config pkg
|
||||||
|
help config logs
|
||||||
|
help config fish-deps
|
||||||
|
|
||||||
|
## Reading the source directly
|
||||||
|
|
||||||
|
`docs/manual/**` is the single source of truth this manual, the man page,
|
||||||
|
and the website are all generated from. Numbered files and directories
|
||||||
|
correspond to the numbered sections in this manual — browse them in any
|
||||||
|
editor, or from a shell:
|
||||||
|
|
||||||
|
cd ~/.config/fish/docs/manual
|
||||||
|
grep -rn "keybindings" .
|
||||||
|
|
||||||
|
Section 5 is the exception. Function entries are generated from the
|
||||||
|
man-page-style comment header above each function in `functions/*.fish`,
|
||||||
|
so the documentation for a command lives beside the code that implements
|
||||||
|
it and cannot drift from it. To read the source for a single function, or
|
||||||
|
to correct its documentation, open the function itself:
|
||||||
|
|
||||||
|
functions/git-clean.fish
|
||||||
|
|
||||||
|
The files under `docs/manual/05-functions/` carry only the category
|
||||||
|
titles, ordering, and search keywords.
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
title: '404'
|
||||||
|
template: splash
|
||||||
|
editUrl: false
|
||||||
|
man: false
|
||||||
|
hero:
|
||||||
|
title: '404'
|
||||||
|
tagline: 'That page doesn''t exist. Check the URL, try using the search bar, or use one of the links below:'
|
||||||
|
---
|
||||||
|
|
||||||
|
<CardGrid>
|
||||||
|
<LinkCard title="Home" description="Return to the main manual page" href="/" />
|
||||||
|
<LinkCard title="Installation" description="Set up the configuration" href="/10-installation/" />
|
||||||
|
<LinkCard title="Troubleshooting" description="Fix common issues" href="/12-troubleshooting/" />
|
||||||
|
<LinkCard title="Function Reference" description="Browse all functions" href="/reference/" />
|
||||||
|
</CardGrid>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
title: FISH-CONFIG
|
||||||
|
section: 7
|
||||||
|
header: Fish Shell Configuration User Manual
|
||||||
|
date: June 2026
|
||||||
|
author: Rootiest
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
---
|
||||||
|
title: Fish Shell Configuration
|
||||||
|
description: Reference manual for the rootiest fish configuration.
|
||||||
|
manTitle: DESCRIPTION
|
||||||
|
sidebar:
|
||||||
|
order: 3
|
||||||
|
helpKeywords:
|
||||||
|
- description
|
||||||
|
- autopair
|
||||||
|
- puffer
|
||||||
|
- puffer-fish
|
||||||
|
- logging-events
|
||||||
|
---
|
||||||
|
|
||||||
|
A production-grade Fish shell configuration targeting Fish 4.x. It provides:
|
||||||
|
|
||||||
|
- Drop-in replacements for common Unix tools (`ls`, `cat`, `rm`, `du`, `ping`, `less`)
|
||||||
|
- Deep Kitty and WezTerm terminal integration: tab/window/pane management from
|
||||||
|
the command line
|
||||||
|
- Optional session logging: terminal scrollback, tmux/zellij panes, and
|
||||||
|
paru/yay output captured to `~/.terminal_history` (off by default; see [C5 Logging](/08-components-reference/05-c5-logging-and-capture/))
|
||||||
|
- Automatic Python virtualenv activation on directory change
|
||||||
|
- Cross-platform package management via pkg and fish-deps
|
||||||
|
- AI scaffolding helpers for Claude Code and Antigravity
|
||||||
|
- Catppuccin Mocha color theme throughout
|
||||||
|
|
||||||
|
<LinkButton href="/10-installation/" icon="cloud-download" style="font-size: 1.25rem; padding: 1rem 1.5rem; margin-right: 1rem;">Install now</LinkButton>
|
||||||
|
<LinkButton href="/reference/" variant="secondary" style="font-size: 1.125rem; padding: 0.85rem 1.25rem;">Functions</LinkButton>
|
||||||
|
<LinkButton href="/08-components-reference/" variant="secondary" style="font-size: 1.125rem; padding: 0.85rem 1.25rem;">Components</LinkButton>
|
||||||
|
|
||||||
|
The configuration uses a structured file tree:
|
||||||
|
|
||||||
|
~/.config/fish/
|
||||||
|
├── config.fish Main entry point; sets env vars and PATH
|
||||||
|
├── conf.d/
|
||||||
|
│ ├── abbr.fish All abbreviations
|
||||||
|
│ ├── autopair.fish Auto-pair brackets and quotes
|
||||||
|
│ ├── cheat.fish cheat.sh tab completions
|
||||||
|
│ ├── done.fish Desktop notifications for long commands
|
||||||
|
│ ├── first_run.fish One-time init: Fisher bootstrap, theme
|
||||||
|
│ ├── key_bindings.fish Custom key bindings and Vi mode
|
||||||
|
│ ├── logging-events.fish C5 event handlers; syncs logging state
|
||||||
|
│ ├── kitty-watcher-reminder.fish C5 per-session Kitty watcher reminder
|
||||||
|
│ ├── paru-wrapper.fish Auto-generates paru logging wrapper
|
||||||
|
│ ├── puffer.fish !! / !$ / ./ expansion
|
||||||
|
│ ├── tmux-logging.fish C5 starts tmux pipe-pane capture
|
||||||
|
│ ├── zellij-logging.fish C5 fish_exit handler for zellij
|
||||||
|
│ ├── sponge_privacy.fish Sponge privacy patterns
|
||||||
|
│ ├── starship.fish fish_prompt shell-integration markers
|
||||||
|
│ ├── tailscale.fish Tailscale CLI tab completions
|
||||||
|
│ ├── theme.fish Catppuccin syntax highlight colors
|
||||||
|
│ ├── tricks.fish PATH, bang-bang helpers, bat man pages
|
||||||
|
│ ├── wakatime.fish WakaTime shell hook
|
||||||
|
│ ├── yay-wrapper.fish Auto-generates yay logging wrapper
|
||||||
|
│ └── zoxide.fish Zoxide z/zi integration; overrides cd
|
||||||
|
├── functions/ Custom functions, one per file
|
||||||
|
├── completions/ Tab completion scripts
|
||||||
|
├── integrations/
|
||||||
|
│ └── fzf.fish FZF Catppuccin theme and key bindings
|
||||||
|
├── scripts/
|
||||||
|
│ ├── clean_progress_log.py Strips typescript animations for clean logs
|
||||||
|
│ └── agents-tools/ AGENTS.md scripts and git hooks
|
||||||
|
└── docs/ Offline documentation and man page
|
||||||
|
├── fish-config.md Primary source manual
|
||||||
|
├── fish-config.1 Compiled man page (auto-generated)
|
||||||
|
├── fish-config.index Section index for help config
|
||||||
|
├── html/ Chunked HTML docs (auto-generated)
|
||||||
|
└── wiki/ Markdown wiki (auto-generated)
|
||||||
|
|
||||||
|
---
|
||||||
@@ -0,0 +1,214 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
"""Shared helpers for the docs/manual SSOT pipeline.
|
||||||
|
|
||||||
|
Frontmatter parsing, deterministic tree ordering, heading level shifts, and
|
||||||
|
the `functions/*.fish` comment-header parser that is the SSOT for Section 5.
|
||||||
|
Used by build-manual.py and verify-manual.py.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
FENCE_RE = re.compile(r"^\s*(```|~~~)")
|
||||||
|
HEADING_RE = re.compile(r"^(#{1,6})(\s)")
|
||||||
|
|
||||||
|
|
||||||
|
def parse(path: Path) -> tuple[dict, str]:
|
||||||
|
"""Split a markdown file into (frontmatter dict, body text).
|
||||||
|
|
||||||
|
Files without a leading `---` block yield an empty dict and the whole
|
||||||
|
text as body. Body is returned with trailing whitespace stripped.
|
||||||
|
"""
|
||||||
|
text = path.read_text()
|
||||||
|
if not text.startswith("---\n"):
|
||||||
|
return {}, text.rstrip()
|
||||||
|
end = text.find("\n---\n", 4)
|
||||||
|
if end == -1:
|
||||||
|
return {}, text.rstrip()
|
||||||
|
fm = yaml.safe_load(text[4:end]) or {}
|
||||||
|
return fm, text[end + 5 :].removeprefix("\n").rstrip()
|
||||||
|
|
||||||
|
|
||||||
|
def serialize(fm: dict, body: str) -> str:
|
||||||
|
"""Render a frontmatter dict and body back into markdown text."""
|
||||||
|
block = yaml.safe_dump(fm, sort_keys=False, allow_unicode=True).rstrip()
|
||||||
|
return f"---\n{block}\n---\n\n{body.rstrip()}\n"
|
||||||
|
|
||||||
|
|
||||||
|
def shift_headings(body: str, by: int) -> str:
|
||||||
|
"""Add `by` levels to every ATX heading, ignoring fenced code blocks.
|
||||||
|
|
||||||
|
Negative values promote headings. Level is clamped to [1, 6].
|
||||||
|
"""
|
||||||
|
if by == 0:
|
||||||
|
return body
|
||||||
|
out, in_fence = [], False
|
||||||
|
for line in body.split("\n"):
|
||||||
|
if FENCE_RE.match(line):
|
||||||
|
in_fence = not in_fence
|
||||||
|
if not in_fence:
|
||||||
|
line = HEADING_RE.sub(
|
||||||
|
lambda m: "#" * max(1, min(6, len(m.group(1)) + by)) + m.group(2), line
|
||||||
|
)
|
||||||
|
out.append(line)
|
||||||
|
return "\n".join(out)
|
||||||
|
|
||||||
|
|
||||||
|
HEADER_LABEL = re.compile(r"^#\s+([A-Z][A-Z ]*[A-Z])\s*$")
|
||||||
|
FUNC_DEF = re.compile(r"^\s*function\s+(\S+)")
|
||||||
|
SECTIONS = (
|
||||||
|
"CATEGORY",
|
||||||
|
"DEPENDENCIES",
|
||||||
|
"SYNOPSIS",
|
||||||
|
"DESCRIPTION",
|
||||||
|
"ARGUMENTS",
|
||||||
|
"EXIT STATUS",
|
||||||
|
"RETURNS",
|
||||||
|
"EXAMPLE",
|
||||||
|
"NOTES",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _header_blocks(lines: list[str]) -> list[tuple[int, dict[str, list[str]]]]:
|
||||||
|
"""Find every man-page comment header in a file's lines.
|
||||||
|
|
||||||
|
Yields (index of the line that ended the block, {LABEL: body lines}).
|
||||||
|
Body lines keep any indentation deeper than the standard `# ` prefix,
|
||||||
|
which is what lets nested option tables survive into the rendered entry.
|
||||||
|
Comment runs carrying no `# LABEL` line at all (the copyright preamble,
|
||||||
|
ordinary inline comments) produce nothing.
|
||||||
|
"""
|
||||||
|
out: list[tuple[int, dict[str, list[str]]]] = []
|
||||||
|
cur: dict[str, list[str]] = {}
|
||||||
|
label: str | None = None
|
||||||
|
for i, line in enumerate(lines + [""]):
|
||||||
|
if not line.startswith("#"):
|
||||||
|
if cur:
|
||||||
|
out.append((i, cur))
|
||||||
|
cur, label = {}, None
|
||||||
|
continue
|
||||||
|
m = HEADER_LABEL.match(line)
|
||||||
|
if m:
|
||||||
|
label = m.group(1)
|
||||||
|
cur.setdefault(label, [])
|
||||||
|
elif label is not None:
|
||||||
|
body = line[1:]
|
||||||
|
cur[label].append(body[3:] if body.startswith(" ") else body.strip())
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def _trailing_blanks(lines: list[str]) -> int:
|
||||||
|
"""Count the blank `#` separator lines closing a section."""
|
||||||
|
n = 0
|
||||||
|
while n < len(lines) and not lines[len(lines) - 1 - n].strip():
|
||||||
|
n += 1
|
||||||
|
return n
|
||||||
|
|
||||||
|
|
||||||
|
def parse_functions(root: Path) -> dict[str, dict[str, list[str]]]:
|
||||||
|
"""Parse the comment header above every documented public function.
|
||||||
|
|
||||||
|
`root` is the repository's `functions/` directory. Returns
|
||||||
|
`{name: {LABEL: [lines]}}`.
|
||||||
|
|
||||||
|
`# CATEGORY` is the opt-in: a header without one produces no entry. That
|
||||||
|
keeps bundled-plugin and prompt internals (`fish_prompt`, `sponge_filter_*`,
|
||||||
|
`fisher`, …) out of the manual with no exclusion list to maintain.
|
||||||
|
|
||||||
|
A file carrying exactly one header is associated with its own stem, so a
|
||||||
|
`function` nested inside a `type -q` guard still resolves. Only files with
|
||||||
|
several headers walk forward to the next `function` definition.
|
||||||
|
"""
|
||||||
|
out: dict[str, dict[str, list[str]]] = {}
|
||||||
|
for path in sorted(root.glob("*.fish")):
|
||||||
|
lines = path.read_text(encoding="utf-8").split("\n")
|
||||||
|
blocks = _header_blocks(lines)
|
||||||
|
for end, sections in blocks:
|
||||||
|
if len(blocks) == 1:
|
||||||
|
name = path.stem
|
||||||
|
else:
|
||||||
|
after = (m.group(1) for ln in lines[end:] if (m := FUNC_DEF.match(ln)))
|
||||||
|
name = next(after, path.stem)
|
||||||
|
if name.startswith("_") or "CATEGORY" not in sections:
|
||||||
|
continue
|
||||||
|
out[name] = {
|
||||||
|
k: v[: len(v) - _trailing_blanks(v)] for k, v in sections.items()
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def parse_abbreviations(root: Path) -> dict[str, list[dict]]:
|
||||||
|
"""Parse annotated abbreviations from conf.d/.
|
||||||
|
|
||||||
|
Returns {category: [{"name": name, "desc": desc}, ...]}
|
||||||
|
"""
|
||||||
|
out: dict[str, list[dict]] = {}
|
||||||
|
for filename in ("abbr.fish", "tricks.fish", "puffer.fish"):
|
||||||
|
path = root / filename
|
||||||
|
if not path.exists():
|
||||||
|
continue
|
||||||
|
lines = path.read_text(encoding="utf-8").split("\n")
|
||||||
|
category = None
|
||||||
|
desc = None
|
||||||
|
name_override = None
|
||||||
|
for line in lines:
|
||||||
|
line = line.strip()
|
||||||
|
if line.startswith("# @category "):
|
||||||
|
category = line[12:].strip()
|
||||||
|
elif line.startswith("# @desc "):
|
||||||
|
desc = line[8:].strip()
|
||||||
|
elif line.startswith("# @name "):
|
||||||
|
name_override = line[8:].strip()
|
||||||
|
elif line.startswith("abbr -a ") or line.startswith("bind ") or line.startswith("alias "):
|
||||||
|
if category and desc:
|
||||||
|
if name_override:
|
||||||
|
name = name_override
|
||||||
|
elif line.startswith("abbr -a "):
|
||||||
|
name = line[8:].strip().split()[0].strip("'\"")
|
||||||
|
elif line.startswith("alias "):
|
||||||
|
name = line[6:].strip().split('=')[0]
|
||||||
|
else:
|
||||||
|
name = "unknown"
|
||||||
|
# Only add if we haven't added this name to this category yet
|
||||||
|
if not any(a["name"] == name for a in out.setdefault(category, [])):
|
||||||
|
out[category].append({
|
||||||
|
"name": name,
|
||||||
|
"desc": desc
|
||||||
|
})
|
||||||
|
category = None
|
||||||
|
desc = None
|
||||||
|
name_override = None
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def _sort_key(entry: Path) -> tuple:
|
||||||
|
"""Order by sidebar.order when present, else by filename. Stable."""
|
||||||
|
target = entry / "index.md" if entry.is_dir() else entry
|
||||||
|
order = None
|
||||||
|
if target.exists():
|
||||||
|
fm, _ = parse(target)
|
||||||
|
order = (fm.get("sidebar") or {}).get("order")
|
||||||
|
return (order is None, order if order is not None else 0, entry.name)
|
||||||
|
|
||||||
|
|
||||||
|
def walk(root: Path, depth: int = 0) -> list[tuple[Path, int]]:
|
||||||
|
"""Return ordered (path, depth) pairs for every markdown file under root.
|
||||||
|
|
||||||
|
A directory sorts at the position of its index.md and its children are
|
||||||
|
emitted immediately afterwards at depth+1.
|
||||||
|
"""
|
||||||
|
entries = [e for e in root.iterdir() if e.is_dir() or e.suffix == ".md"]
|
||||||
|
result: list[tuple[Path, int]] = []
|
||||||
|
for entry in sorted(entries, key=_sort_key):
|
||||||
|
if entry.is_dir():
|
||||||
|
index = entry / "index.md"
|
||||||
|
if index.exists():
|
||||||
|
result.append((index, depth))
|
||||||
|
result.extend(walk(entry, depth + 1))
|
||||||
|
elif entry.name != "index.md" or depth == 0:
|
||||||
|
result.append((entry, depth))
|
||||||
|
return result
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# build output
|
||||||
|
dist/
|
||||||
|
# generated types
|
||||||
|
.astro/
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# logs
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
|
||||||
|
# environment variables
|
||||||
|
.env
|
||||||
|
.env.production
|
||||||
|
|
||||||
|
# macOS-specific files
|
||||||
|
.DS_Store
|
||||||
Vendored
+4
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"recommendations": ["astro-build.astro-vscode"],
|
||||||
|
"unwantedRecommendations": []
|
||||||
|
}
|
||||||
Vendored
+11
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"command": "./node_modules/.bin/astro dev",
|
||||||
|
"name": "Development server",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "node-terminal"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# fish-config docs site
|
||||||
|
|
||||||
|
[Starlight](https://starlight.astro.build) site for the
|
||||||
|
[fish-config](https://git.rootiest.dev/rootiest/fish-config) manual.
|
||||||
|
|
||||||
|
## Generated, not authored
|
||||||
|
|
||||||
|
Everything under `src/content/docs/` is generated — **do not edit it
|
||||||
|
directly**, changes will be overwritten. The sources are:
|
||||||
|
|
||||||
|
- `docs/manual/**` — prose for every section except the functions reference
|
||||||
|
- `functions/*.fish` comment headers — the functions reference (Section 5)
|
||||||
|
|
||||||
|
Regenerate from the repo root:
|
||||||
|
|
||||||
|
```fish title="regenerate the site content"
|
||||||
|
python3 docs/build-manual.py --site
|
||||||
|
```
|
||||||
|
|
||||||
|
`docs/verify-manual.py` validates both sources before you build; run it
|
||||||
|
first if you've touched a header or a manual page.
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
```fish title="local dev server"
|
||||||
|
cd docs/site
|
||||||
|
npm install
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deploy
|
||||||
|
|
||||||
|
Built and deployed to Cloudflare Pages by the Gitea Actions workflow on
|
||||||
|
every push to `main` — there's no manual deploy step.
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { defineConfig } from 'astro/config';
|
||||||
|
import starlight from '@astrojs/starlight';
|
||||||
|
import starlightLinksValidator from 'starlight-links-validator';
|
||||||
|
import starlightCatppuccin from '@catppuccin/starlight';
|
||||||
|
import sidebar from './src/sidebar.json' with { type: 'json' };
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
prerenderConflictBehavior: 'ignore',
|
||||||
|
site: 'https://fish.rootiest.fyi',
|
||||||
|
integrations: [
|
||||||
|
starlight({
|
||||||
|
title: 'Rootiest Fish Config',
|
||||||
|
description: 'Reference manual for the rootiest fish configuration.',
|
||||||
|
favicon: '/favicon.svg',
|
||||||
|
logo: {
|
||||||
|
src: './src/assets/logo.svg',
|
||||||
|
},
|
||||||
|
social: [
|
||||||
|
{
|
||||||
|
icon: 'code-branch',
|
||||||
|
label: 'Gitea',
|
||||||
|
href: 'https://git.rootiest.dev/rootiest/fish-config',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
head: [
|
||||||
|
{
|
||||||
|
tag: 'script',
|
||||||
|
content: 'document.addEventListener("DOMContentLoaded", () => { document.querySelectorAll("starlight-file-tree").forEach(tree => { tree.querySelectorAll("details").forEach((d, i) => { if (i !== 0) d.removeAttribute("open"); }); }); });',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
starlightLinksValidator(),
|
||||||
|
starlightCatppuccin({
|
||||||
|
dark: { flavor: "mocha", accent: "green" },
|
||||||
|
light: { flavor: "latte", accent: "sky" },
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
expressiveCode: {
|
||||||
|
// Shiki ships both Catppuccin flavours; Starlight picks by the
|
||||||
|
// reader's colour scheme, matching the palette in catppuccin.css.
|
||||||
|
themes: ['catppuccin-mocha', 'catppuccin-latte'],
|
||||||
|
styleOverrides: {
|
||||||
|
borderRadius: '0.4rem',
|
||||||
|
borderColor: 'var(--sl-color-gray-5)',
|
||||||
|
codeFontSize: '0.875rem',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sidebar,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
Generated
+7062
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user