mirror of
https://github.com/jimeh/dotfiles.git
synced 2026-02-19 13:46:41 +00:00
Compare commits
533 Commits
cb7ff641f0
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
919c5d48de | ||
|
d3ef296e84
|
|||
|
39f2d3094c
|
|||
|
e2d2e4ec13
|
|||
|
|
9bf0ffd5d7 | ||
|
|
ae207e49bd | ||
|
a76c67542f
|
|||
|
6900c31b3a
|
|||
|
|
83d043f186 | ||
|
eb3ecdce75
|
|||
|
9e5784d741
|
|||
|
051731d110
|
|||
|
c83cd5e62b
|
|||
|
54fac673e0
|
|||
|
e542560a67
|
|||
|
ca42166e11
|
|||
|
9c2e3b7343
|
|||
|
|
f5245da82a | ||
|
|
cc3dd3fe0e | ||
|
|
1c0f58ef55 | ||
|
|
220461bd9a | ||
|
|
e34efe233e | ||
|
|
3a14e2302f | ||
|
7911beee79
|
|||
|
c4924a8cfc
|
|||
|
e38a4f6b73
|
|||
|
|
f3bb188938 | ||
|
|
f1901b81ad | ||
|
|
ab9042fbae | ||
|
|
c0694b0494 | ||
|
cb72a6e190
|
|||
|
b38ab73624
|
|||
|
6dc701a4f7
|
|||
|
3ef428c5ea
|
|||
|
a6af299d8d
|
|||
|
|
a954f2b588 | ||
|
|
4f831ccd2e | ||
|
|
b72042cd1f | ||
|
|
75116ac623 | ||
|
f92e4b9646
|
|||
|
|
f7dd4b41fd | ||
|
4909c6a779
|
|||
|
eed33bf54c
|
|||
|
711b8f7678
|
|||
|
1822f82401
|
|||
|
7c04e49858
|
|||
|
3bb36f8b32
|
|||
|
4756212c32
|
|||
|
de6bb30eae
|
|||
|
079ec5177f
|
|||
|
666c60b89d
|
|||
|
e86ff34b2e
|
|||
|
fcbcce79f6
|
|||
|
13b2b58b67
|
|||
|
dee407ffc7
|
|||
|
192e6d6a21
|
|||
|
c2ab0a9362
|
|||
|
|
17b96034b6 | ||
|
|
7248d531b8 | ||
|
e60b35ecb4
|
|||
|
f0e903f102
|
|||
|
6cba7534cf
|
|||
|
1808ccde8b
|
|||
|
0adfe2a389
|
|||
|
4c17e33786
|
|||
|
|
f862c93970 | ||
|
f2be6869d2
|
|||
|
74c4df5974
|
|||
|
78c2706301
|
|||
|
1b2c9351cc
|
|||
|
0211c75b1b
|
|||
|
76bbdfb25f
|
|||
|
d79d05b551
|
|||
|
|
699b4a05d4 | ||
|
b7aef0bb99
|
|||
|
aa7b647a7f
|
|||
|
|
9cd09904a4 | ||
|
|
ebf9c4455c | ||
|
|
4007b32303 | ||
|
|
1dd9b6664d | ||
|
|
62b252f570 | ||
|
9e1fd19992
|
|||
|
c939a13be8
|
|||
|
6fcc5013e9
|
|||
|
86c5a45570
|
|||
|
9fd9b794d5
|
|||
|
ead236947f
|
|||
|
|
93eb2af279 | ||
|
|
68a5b5dfb9 | ||
|
|
204d274cee | ||
|
|
086d80d6bd | ||
|
|
4baed4f299 | ||
|
447fcd04a8
|
|||
|
83c7fb10a2
|
|||
|
509b2e89e6
|
|||
|
|
50004fcb74 | ||
|
d04be47100
|
|||
|
e3377c7dbe
|
|||
|
6507f123cb
|
|||
|
0c46b38c5f
|
|||
|
|
1f558c9f95 | ||
|
0224bd608c
|
|||
|
70e616332e
|
|||
|
fedb2a78ba
|
|||
|
e47b73d645
|
|||
|
bf79e3aa4c
|
|||
|
add5fe566c
|
|||
|
e63ea227f9
|
|||
|
eb7f92740c
|
|||
|
e835afbd05
|
|||
|
94887fe5f1
|
|||
|
7e3b5ae4f9
|
|||
|
1c2feb9b8b
|
|||
|
4e7a48fb2c
|
|||
|
fb2da8181b
|
|||
|
734947c0e7
|
|||
|
124fcd921f
|
|||
|
|
753b4cec41 | ||
|
|
31e79a0d64 | ||
|
9eb9dd21b0
|
|||
|
|
4292fc70e8 | ||
|
|
c5e6591d7f | ||
|
|
93e46d8edc | ||
|
9fc5722fa7
|
|||
|
36195046d4
|
|||
|
d2b5cd53b0
|
|||
|
ed14e9a73d
|
|||
|
b572a346fa
|
|||
|
60cf0d1e33
|
|||
|
525fe77e62
|
|||
|
9315ca98bb
|
|||
|
5bd7292a5e
|
|||
|
456547a278
|
|||
|
fcf092041a
|
|||
|
c134beccea
|
|||
|
6eb38e87f7
|
|||
|
c2ae58077a
|
|||
|
cf1c7de954
|
|||
|
1ebbcaf386
|
|||
|
8dc375887c
|
|||
|
d87d60445e
|
|||
|
|
12bee562c3 | ||
|
b585142dca
|
|||
|
|
8b7de2514e | ||
|
|
f80885f663 | ||
|
|
899828ad0c | ||
|
|
db5efc926c | ||
|
68f828b356
|
|||
|
1e536231f1
|
|||
|
6ca847f9bc
|
|||
|
02311a6b3e
|
|||
|
4d3b0e5c79
|
|||
|
|
da24c81f93 | ||
|
|
0494075eb0 | ||
|
|
56c3b49bef | ||
|
|
d2ee3df9ed | ||
|
|
0084d78885 | ||
|
|
4a7c880a3a | ||
|
9760c4a2aa
|
|||
|
1f61ddd8e4
|
|||
|
52f4d43ddf
|
|||
|
0d02455a73
|
|||
|
4d76bb94b9
|
|||
|
708917f58f
|
|||
|
4551336767
|
|||
|
6e6755231c
|
|||
|
69581a3529
|
|||
|
f4563e03fd
|
|||
|
327905fb05
|
|||
|
|
531bf0bd0f | ||
|
|
f4f9b055bb | ||
|
|
e67bf554a2 | ||
|
8a77fc622c
|
|||
|
4e8a756bec
|
|||
|
9fbed8d2ba
|
|||
|
63a7285d05
|
|||
|
28eea46178
|
|||
|
b1ec71d45c
|
|||
|
4bd7fbcc19
|
|||
|
|
27a3193c01 | ||
|
|
6a7cca4597 | ||
|
|
7f937b2777 | ||
|
|
c9ef1aa07c | ||
|
|
12c3e4e2c0 | ||
|
|
8153faae39 | ||
|
|
9d0dc840dd | ||
|
|
1227c603af | ||
|
a95fe29e8e
|
|||
|
842fe398d7
|
|||
|
cebbd21e9b
|
|||
|
a6d649dbb5
|
|||
|
|
53effb7185 | ||
|
|
5a33d6e345 | ||
|
|
79b82d6ce9 | ||
|
|
0fdc9854fe | ||
|
55d6c9ccad
|
|||
|
d8d77c5f50
|
|||
|
|
b550696164 | ||
|
|
71192d2555 | ||
|
|
1547265931 | ||
|
|
6cece38916 | ||
|
|
f71b6376e8 | ||
|
1f977a79ff
|
|||
|
7cbdf277ff
|
|||
|
d0dc7b9068
|
|||
|
989b90822f
|
|||
|
043ab9af6a
|
|||
|
|
78bf38cc7d | ||
|
f1243b09a8
|
|||
|
f3df7e2253
|
|||
|
37a7552518
|
|||
|
|
3dd0e620fd | ||
|
|
1e87166ea5 | ||
|
|
c35363ac8f | ||
|
|
497fe4c9b3 | ||
|
|
9ca2e7ead6 | ||
|
|
379f28175a | ||
|
|
fed65960f2 | ||
|
|
f421ba578b | ||
|
f9af2de78f
|
|||
|
cd497851bd
|
|||
|
035a43d32e
|
|||
|
32d6e8ebba
|
|||
|
84486c881c
|
|||
|
f2f195d15f
|
|||
|
36ccaa89e2
|
|||
|
f6dc89641a
|
|||
|
537ca9f9dd
|
|||
|
b6c291c44c
|
|||
|
1ef2937eb4
|
|||
|
d76e2f771e
|
|||
|
edd534d50e
|
|||
|
89aeb4a960
|
|||
|
|
144de73855 | ||
|
|
06f91b1d79 | ||
|
65bee1192e
|
|||
|
03eb561f1f
|
|||
|
|
7064604079 | ||
|
|
b8ca8c0268 | ||
|
9680f81955
|
|||
|
0be2643aa4
|
|||
|
|
e6d81a0903 | ||
|
|
62f5251774 | ||
|
|
2be6239e18 | ||
|
|
7766d46bd3 | ||
|
e42f9794a5
|
|||
|
|
b6ac9ce2ac | ||
|
|
0cb2d3ab27 | ||
|
|
a1a078c976 | ||
|
4616736544
|
|||
|
70fe417553
|
|||
|
|
726de4a6d7 | ||
|
2b54755e91
|
|||
|
3ec3884108
|
|||
|
ca8c913eb3
|
|||
|
ffe5933b17
|
|||
|
10144dfa16
|
|||
|
6eee7b019a
|
|||
|
fed6251aa7
|
|||
|
33bcfd70be
|
|||
|
00d6815373
|
|||
|
|
24aab0403e | ||
|
|
d560688c58 | ||
|
|
9e200139cc | ||
|
|
8ecb6a1d84 | ||
|
|
1ab8503b1c | ||
|
|
0f0efd5917 | ||
|
|
bb0518a166 | ||
|
bb538ee33b
|
|||
|
9e9818456d
|
|||
|
151620c15b
|
|||
|
3d008b827d
|
|||
|
8b22da930e
|
|||
|
eea10a67e0
|
|||
|
eadb0fb6e4
|
|||
|
|
9a501b438b | ||
|
|
e31301d0ff | ||
|
|
d400b87228 | ||
|
|
cc7d4a10d2 | ||
|
|
2242bd9580 | ||
|
|
fdc7fcafc6 | ||
|
0c419db04e
|
|||
|
9d29136ae6
|
|||
|
|
b56b651790 | ||
|
a86cedbcb2
|
|||
|
5b300e7501
|
|||
|
|
714938a289 | ||
|
2ab4549060
|
|||
|
938fd1be31
|
|||
|
e3cd54b9da
|
|||
|
2f4385a9c6
|
|||
|
f89466da66
|
|||
|
916b3967e8
|
|||
|
d2d324d1f0
|
|||
|
2c051577b7
|
|||
|
93688e3f2b
|
|||
|
f4a409071e
|
|||
|
b753d6af61
|
|||
|
5cafa5c9d4
|
|||
|
fcbed7dc82
|
|||
|
79d1049d93
|
|||
|
6139832568
|
|||
|
494578b1ad
|
|||
|
|
831e4854af | ||
|
|
cf161df584 | ||
|
30c8ab45af
|
|||
|
cb7d47965d
|
|||
|
ff3fab8c39
|
|||
|
|
13ea7e419b | ||
|
|
5990bc5975 | ||
|
|
4f99ba5001 | ||
|
|
ce00fc9793 | ||
|
0ab34484d0
|
|||
|
743f99db4f
|
|||
|
d3b5a0c2ab
|
|||
|
5f0330dcaf
|
|||
|
154b9b1938
|
|||
|
25fa7329f8
|
|||
|
93dbc451e3
|
|||
|
|
4e461ad88c | ||
|
97a7844508
|
|||
|
fde1c930be
|
|||
|
32d6142548
|
|||
|
|
fc4ebfd5fd | ||
|
|
ae53c3fb23 | ||
|
|
3072c61568 | ||
|
|
576d03a17a | ||
|
|
e0e872227f | ||
|
|
9135f58a12 | ||
|
|
4ea6ee4ade | ||
|
|
ad66b0251f | ||
|
e2f55741aa
|
|||
|
|
9791d9e304 | ||
|
|
aa17e6fa66 | ||
|
|
d9cb73260e | ||
|
12b5ecee91
|
|||
|
|
de4fad562a | ||
|
|
6c80e27c64 | ||
|
de14e784c3
|
|||
|
ad40c1e2e3
|
|||
|
c5a5e9f108
|
|||
|
54aed5d054
|
|||
|
6562df1c19
|
|||
|
ddbbe283ff
|
|||
|
98f0b2ec66
|
|||
|
3a6e6a5256
|
|||
|
43be9196eb
|
|||
|
e6572caac9
|
|||
|
e224c2219c
|
|||
|
4a63857a49
|
|||
|
359f0642a6
|
|||
|
6f720ba985
|
|||
|
6858f50757
|
|||
|
4e5644de9d
|
|||
|
90617b48e0
|
|||
|
995181f67f
|
|||
|
6336532081
|
|||
|
f30c675f3b
|
|||
|
53052def08
|
|||
|
f399f5f085
|
|||
|
|
f3bf4ff98d | ||
|
|
ee5c2284ea | ||
|
|
430e9053be | ||
|
|
ee559256c1 | ||
|
|
ba5ea568c8 | ||
|
|
7fff0e62af | ||
|
|
4e5259cd1e | ||
|
|
594022d8df | ||
|
|
f0c38533f5 | ||
|
|
bab3b33c97 | ||
|
698860e72c
|
|||
|
3201add496
|
|||
|
0704f6dbcc
|
|||
|
abcff44c09
|
|||
|
f7e1cb03e7
|
|||
|
8e67b0066a
|
|||
|
9ece01a77e
|
|||
|
2cbd074bac
|
|||
|
1158360c21
|
|||
|
24f6280608
|
|||
|
|
5e3beb61dc | ||
|
|
9b8135e84d | ||
|
|
2569e63464 | ||
|
284e558669
|
|||
|
f50e41b3bb
|
|||
|
|
770486fa48 | ||
|
6f7dda418d
|
|||
|
5b28ca6028
|
|||
|
7a81ddff58
|
|||
|
e77f402afd
|
|||
|
7fec239046
|
|||
|
c091274fb7
|
|||
|
010c790922
|
|||
|
20569a2a5e
|
|||
|
a39e2d8a41
|
|||
|
cacc0b09f4
|
|||
|
f6fcd94f2e
|
|||
|
b686b420e6
|
|||
|
|
b0f8500e59 | ||
|
d1116deb8a
|
|||
|
9dd02eadc4
|
|||
|
2cf962cb6e
|
|||
|
|
7660ac3afa | ||
|
|
b9e733615d | ||
|
|
347db4ef48 | ||
|
|
8e5537f264 | ||
|
9c041a4f9a
|
|||
|
a7ce4a5788
|
|||
|
779a589a3d
|
|||
|
1829517c54
|
|||
|
0b183f8acd
|
|||
|
ffa09cbf4c
|
|||
|
5cde6d16c0
|
|||
|
1d3d630223
|
|||
|
32b25c3717
|
|||
|
e30d66b7e7
|
|||
|
edcf9c122d
|
|||
|
65544c24cc
|
|||
|
6cd1d787c7
|
|||
|
c04e2c77a8
|
|||
|
4f1589d18c
|
|||
|
6a7b67a889
|
|||
|
40d191251b
|
|||
|
e911f1ecb9
|
|||
|
4fb30f9288
|
|||
|
|
240a970ba5 | ||
|
|
a0ac91449b | ||
|
|
9b1b1af109 | ||
|
71212cfe34
|
|||
|
efd401bc23
|
|||
|
f8ed994dd5
|
|||
|
f15bacb858
|
|||
|
bf27ad21e4
|
|||
|
f6ed37534a
|
|||
|
e51d08c738
|
|||
|
259244eb81
|
|||
|
8c5b2ac4c6
|
|||
|
86e2b4012f
|
|||
|
ef6fb00128
|
|||
|
bf92527b6a
|
|||
|
f4ce515973
|
|||
|
35a6ba4ab9
|
|||
|
9526b57d38
|
|||
|
a304b0bb26
|
|||
|
46ab18b0fd
|
|||
|
10bfd9a032
|
|||
|
a5fc1a070a
|
|||
|
08011c0fef
|
|||
|
78463acf94
|
|||
|
df56386d7a
|
|||
|
12505e939a
|
|||
|
5ee117846b
|
|||
|
fea1e8bd99
|
|||
|
10bf02e1b4
|
|||
|
db7a97fa6d
|
|||
|
772295a5a0
|
|||
|
871fefce04
|
|||
|
319ad47d34
|
|||
|
047d11653b
|
|||
|
407e02895d
|
|||
|
b7ff042053
|
|||
|
c137a5978a
|
|||
|
0effd071f3
|
|||
|
0b432f137d
|
|||
|
49a28ce05e
|
|||
|
19aa1b1730
|
|||
|
6c9703520c
|
|||
|
c51fde5e70
|
|||
|
f6e49a661b
|
|||
|
c4cd5eaa2b
|
|||
|
5fba8ec527
|
|||
|
e87062e8ee
|
|||
|
4cd9893126
|
|||
|
5eb71b08a8
|
|||
|
61d072a36c
|
|||
|
6fe27107f0
|
|||
|
e24d969a1e
|
|||
|
73556e6f6a
|
|||
|
f005414ab2
|
|||
|
266c6dcfac
|
|||
|
5feea990d4
|
|||
|
e1105afa0c
|
|||
|
fc33b59dc8
|
|||
|
3de163d673
|
|||
|
01fc707a2b
|
|||
|
e66883cf73
|
|||
|
fd6aaf0168
|
|||
|
a142363fa7
|
|||
|
9490cabd3d
|
|||
|
ab0de76e79
|
|||
|
fd94bd2774
|
|||
|
214d82f0aa
|
|||
|
b5a3dc2e4e
|
|||
|
415fc774b1
|
|||
|
fcb8b04795
|
|||
|
50b21937b3
|
|||
|
43d8a4ad9f
|
|||
|
7b52ea47ec
|
|||
|
77367ea1db
|
|||
|
84bb6dfb80
|
|||
|
96ed44adf3
|
|||
|
06b5b5cd39
|
|||
|
cc3121e472
|
|||
|
900e69a07f
|
|||
|
673bbecf59
|
|||
|
10afd47a2b
|
|||
|
881e5f4d12
|
|||
|
86efc403d1
|
|||
|
0afaeaa9a2
|
|||
|
2a8e815db1
|
|||
|
8830fa2af1
|
|||
|
08c8ac784d
|
|||
|
6e3154deba
|
|||
|
58f7306c6f
|
|||
|
32b933c419
|
|||
|
7fbc1e11d4
|
|||
|
c101c417fd
|
|||
|
72dde13eb7
|
|||
|
664f06bbdb
|
|||
|
885fd26901
|
|||
|
9abb969dbb
|
|||
|
4bf199c73b
|
|||
|
ef48ac629a
|
|||
|
0a17bbfadb
|
|||
|
4ff776f1f3
|
|||
|
fcf9ee7e2a
|
|||
|
9b63c538c2
|
|||
|
14c58e849f
|
|||
|
204a8979da
|
|||
|
c7ea3d186a
|
|||
|
78caf6e939
|
|||
|
e252161208
|
|||
|
9244c7f92b
|
2
.cursorignore
Normal file
2
.cursorignore
Normal file
@@ -0,0 +1,2 @@
|
||||
# Add directories or file patterns to ignore during indexing (e.g. foo/ or *.csv)
|
||||
private/*
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -8,3 +8,4 @@ Icon*
|
||||
bin/boot2docker.iso
|
||||
private/*
|
||||
tmux/plugins/*
|
||||
cursor/cache/*
|
||||
|
||||
5
.harper-dictionary.txt
Normal file
5
.harper-dictionary.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
RPCError
|
||||
SwiftBar
|
||||
Xbar's
|
||||
argv
|
||||
yieldparam
|
||||
9
.vscode/extensions.json
vendored
Normal file
9
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
// List of extensions which should be recommended for users of this workspace.
|
||||
"recommendations": [
|
||||
// Allows for use of settings.shared.json and settings.local.json.
|
||||
"swellaby.workspace-config-plus"
|
||||
]
|
||||
}
|
||||
50
.vscode/settings.shared.json
vendored
Normal file
50
.vscode/settings.shared.json
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"aegisub",
|
||||
"appcleaner",
|
||||
"appdir",
|
||||
"apphider",
|
||||
"apptoggle",
|
||||
"aquaproj",
|
||||
"atinit",
|
||||
"autodmg",
|
||||
"binstall",
|
||||
"colordiff",
|
||||
"correctall",
|
||||
"difftastic",
|
||||
"dirstat",
|
||||
"dmgbuild",
|
||||
"DOTBIN",
|
||||
"DOTPFILES",
|
||||
"DOTZSH",
|
||||
"fonttools",
|
||||
"funcs",
|
||||
"geckodriver",
|
||||
"getopt",
|
||||
"gitu",
|
||||
"Grooff",
|
||||
"grpcurl",
|
||||
"htmllint",
|
||||
"httpsnippet",
|
||||
"hwatch",
|
||||
"INFOPATH",
|
||||
"jwtui",
|
||||
"keycastr",
|
||||
"kubecm",
|
||||
"KUBECONFIG",
|
||||
"localtunnel",
|
||||
"PLISTS",
|
||||
"rakyll",
|
||||
"rapidapi",
|
||||
"RUSTC",
|
||||
"shellenv",
|
||||
"stfolder",
|
||||
"stignore",
|
||||
"tlrc",
|
||||
"watchexec",
|
||||
"zdharma",
|
||||
"zicdreplay",
|
||||
"zicompinit",
|
||||
"zinitrc"
|
||||
]
|
||||
}
|
||||
169
Brewfile
169
Brewfile
@@ -7,14 +7,13 @@
|
||||
hostname = `hostname -s`.strip
|
||||
cask_args appdir: '/Applications'
|
||||
|
||||
tap 'homebrew/cask'
|
||||
tap 'homebrew/cask-drivers'
|
||||
tap 'homebrew/cask-versions'
|
||||
|
||||
#
|
||||
# Command-Line Tools (Brew)
|
||||
#
|
||||
|
||||
brew '1password-cli'
|
||||
brew 'ack'
|
||||
brew 'aspell'
|
||||
brew 'bash'
|
||||
@@ -22,58 +21,43 @@ brew 'caddy'
|
||||
brew 'cmake'
|
||||
brew 'colordiff'
|
||||
brew 'coreutils'
|
||||
brew 'ctop'
|
||||
brew 'efm-langserver'
|
||||
brew 'fd'
|
||||
brew 'ffmpeg'
|
||||
brew 'geckodriver'
|
||||
brew 'git'
|
||||
brew 'git-crypt'
|
||||
brew 'git-delta'
|
||||
brew 'go'
|
||||
brew 'golangci-lint'
|
||||
brew 'goreleaser'
|
||||
brew 'hadolint'
|
||||
brew 'hey'
|
||||
brew 'highlight'
|
||||
brew 'htop'
|
||||
brew 'httpie'
|
||||
brew 'jq'
|
||||
brew 'less'
|
||||
brew 'libvterm'
|
||||
brew 'libyaml'
|
||||
brew 'logrotate'
|
||||
brew 'lua'
|
||||
brew 'luarocks'
|
||||
brew 'make'
|
||||
brew 'mas'
|
||||
brew 'mosh', args: ['HEAD']
|
||||
brew 'mergiraf'
|
||||
brew 'mosh'
|
||||
brew 'node'
|
||||
brew 'pandoc'
|
||||
brew 'peco'
|
||||
brew 'pgformatter'
|
||||
brew 'pv'
|
||||
brew 'readline'
|
||||
brew 'redis'
|
||||
brew 'ripgrep'
|
||||
brew 'rustup-init'
|
||||
brew 'shellcheck'
|
||||
brew 'shfmt'
|
||||
brew 'source-highlight'
|
||||
brew 'svn'
|
||||
brew 'telnet'
|
||||
brew 'terraform'
|
||||
brew 'terraform-ls'
|
||||
brew 'tflint'
|
||||
brew 'the_silver_searcher'
|
||||
brew 'tldr'
|
||||
brew 'tmux'
|
||||
brew 'trash'
|
||||
brew 'tree'
|
||||
brew 'watch'
|
||||
brew 'wget'
|
||||
brew 'yank'
|
||||
brew 'zsh'
|
||||
|
||||
tap 'heroku/brew'
|
||||
brew 'heroku'
|
||||
tap 'MisterTea/et'
|
||||
brew 'MisterTea/et/et'
|
||||
|
||||
#
|
||||
# Desktop Apps (Cask)
|
||||
@@ -83,29 +67,22 @@ brew 'heroku'
|
||||
cask '1password'
|
||||
cask 'alfred'
|
||||
cask 'appcleaner'
|
||||
cask 'bartender'
|
||||
cask 'betterzip'
|
||||
cask 'bitbar'
|
||||
cask 'daisydisk'
|
||||
cask 'firefox'
|
||||
cask 'fluid'
|
||||
cask 'google-chrome'
|
||||
cask 'gpg-suite'
|
||||
cask 'hammerspoon'
|
||||
cask 'handbrake'
|
||||
cask 'iina'
|
||||
cask 'intel-power-gadget'
|
||||
cask 'istat-menus'
|
||||
cask 'iterm2'
|
||||
cask 'karabiner-elements'
|
||||
cask 'logitech-options'
|
||||
cask 'mplayerx'
|
||||
cask 'name-mangler'
|
||||
cask 'osxfuse'
|
||||
cask 'microsoft-edge'
|
||||
cask 'orion'
|
||||
cask 'resolutionator'
|
||||
cask 'soulver2'
|
||||
cask 'stay'
|
||||
cask 'suspicious-package'
|
||||
cask 'transmission'
|
||||
cask 'ubersicht'
|
||||
cask 'vlc'
|
||||
cask 'xbar'
|
||||
|
||||
# Fonts
|
||||
tap 'homebrew/cask-fonts'
|
||||
@@ -113,61 +90,30 @@ cask 'font-clear-sans'
|
||||
cask 'font-menlo-for-powerline'
|
||||
cask 'font-office-code-pro'
|
||||
cask 'font-open-sans'
|
||||
cask 'font-open-sans-condensed'
|
||||
cask 'font-terminus'
|
||||
cask 'font-ubuntu'
|
||||
cask 'font-ubuntu-mono-derivative-powerline'
|
||||
cask 'font-xkcd'
|
||||
|
||||
# Work Apps
|
||||
cask 'bbedit'
|
||||
cask 'chromedriver'
|
||||
cask 'cyberduck'
|
||||
cask 'dash'
|
||||
cask 'docker'
|
||||
cask 'drawio'
|
||||
cask 'fork'
|
||||
cask 'gitx'
|
||||
cask 'hex-fiend'
|
||||
cask 'insomnia'
|
||||
cask 'kaleidoscope'
|
||||
cask 'keycastr'
|
||||
cask 'licecap'
|
||||
cask 'paw'
|
||||
cask 'postico'
|
||||
cask 'robo-3t'
|
||||
cask 'orbstack'
|
||||
cask 'rapidapi'
|
||||
cask 'sequel-pro'
|
||||
cask 'slack'
|
||||
cask 'transmit'
|
||||
cask 'vagrant'
|
||||
cask 'virtualbox'
|
||||
cask 'visual-studio-code'
|
||||
cask 'utm'
|
||||
cask 'visual-studio-code-insiders'
|
||||
cask 'zoom'
|
||||
|
||||
# noct
|
||||
if hostname == 'noct'
|
||||
brew 'ffmpeg', args: %w[
|
||||
with-fdk-aac
|
||||
with-libass
|
||||
with-librsvg
|
||||
with-libsoxr
|
||||
with-libssh
|
||||
with-libvidstab
|
||||
with-openh264
|
||||
with-openssl
|
||||
with-rubberband
|
||||
with-srt
|
||||
with-tesseract
|
||||
with-webp
|
||||
]
|
||||
brew 'get_iplayer'
|
||||
|
||||
cask 'basecamp'
|
||||
|
||||
brew 'go-jsonnet'
|
||||
brew 'influxdb'
|
||||
brew 'jsonnet-bundler'
|
||||
brew 'kubernetes-cli'
|
||||
brew 'kubernetes-helm'
|
||||
brew 'kubectx'
|
||||
brew 'mariadb'
|
||||
cask 'lens'
|
||||
|
||||
@@ -175,6 +121,9 @@ if hostname == 'noct'
|
||||
brew 'node_exporter'
|
||||
brew 'prometheus'
|
||||
|
||||
tap 'jimeh/macos-battery-exporter'
|
||||
brew 'macos-battery-exporter'
|
||||
|
||||
cask '4k-video-downloader'
|
||||
cask 'adobe-creative-cloud'
|
||||
cask 'aegisub'
|
||||
@@ -185,26 +134,34 @@ if hostname == 'noct'
|
||||
cask 'autodmg'
|
||||
cask 'avidemux'
|
||||
cask 'balenaetcher'
|
||||
cask 'bartender'
|
||||
cask 'betterzip'
|
||||
cask 'calibre'
|
||||
cask 'deluge'
|
||||
cask 'discord'
|
||||
cask 'dropbox'
|
||||
cask 'carbon-copy-cloner'
|
||||
cask 'daisydisk'
|
||||
cask 'discord-ptb'
|
||||
cask 'dropshare'
|
||||
cask 'element'
|
||||
cask 'epic-games'
|
||||
cask 'evernote'
|
||||
cask 'get-iplayer-automator'
|
||||
cask 'gog-galaxy'
|
||||
cask 'handbrake'
|
||||
cask 'istumbler'
|
||||
cask 'istat-menus'
|
||||
cask 'kaleidoscope2'
|
||||
cask 'kapitainsky-rclone-browser'
|
||||
cask 'keybase'
|
||||
cask 'lastfm'
|
||||
cask 'ledger-live'
|
||||
cask 'little-snitch'
|
||||
cask 'lm-studio'
|
||||
cask 'mailplane'
|
||||
cask 'makemkv'
|
||||
cask 'messenger'
|
||||
cask 'mkvtoolnix'
|
||||
cask 'monodraw'
|
||||
cask 'name-mangler'
|
||||
cask 'notion'
|
||||
cask 'obsidian'
|
||||
cask 'openemu'
|
||||
cask 'paparazzi'
|
||||
cask 'parallels'
|
||||
@@ -219,50 +176,70 @@ if hostname == 'noct'
|
||||
cask 'quicklook-csv'
|
||||
cask 'quicklook-json'
|
||||
cask 'quicklookapk'
|
||||
cask 'raspberry-pi-imager'
|
||||
cask 'scroll-reverser'
|
||||
cask 'sixtyforce'
|
||||
cask 'skype'
|
||||
cask 'soulver2'
|
||||
cask 'soundsource'
|
||||
cask 'spotify'
|
||||
cask 'steam'
|
||||
cask 'suspicious-package'
|
||||
cask 'tableplus'
|
||||
cask 'teamspeak-client'
|
||||
cask 'transmission'
|
||||
cask 'transmit'
|
||||
cask 'upscayl'
|
||||
cask 'virtualc64'
|
||||
cask 'viscosity'
|
||||
cask 'vmware-fusion'
|
||||
cask 'vnc-viewer'
|
||||
cask 'webpquicklook'
|
||||
cask 'whatsapp'
|
||||
cask 'xld'
|
||||
cask 'zoom'
|
||||
|
||||
# Mac App Store Apps
|
||||
mas 'Apple Remote Desktop', id: 409_907_375
|
||||
mas 'Awaken', id: 404_221_531
|
||||
mas 'Bear', id: 1_091_189_122
|
||||
mas 'Blackmagic Disk Speed Test', id: 425_264_550
|
||||
mas 'Calca', id: 635_758_264
|
||||
mas 'ColorSlurp', id: 1_287_239_339
|
||||
mas 'Flame', id: 325_206_381
|
||||
mas 'GoodNotes 5', id: 1_444_383_602
|
||||
mas 'HTTP Client', id: 418_138_339
|
||||
mas 'HiddenMe', id: 467_040_476
|
||||
mas 'Medis', id: 1_063_631_769
|
||||
mas 'Microsoft Remote Desktop 10', id: 1_295_203_466
|
||||
mas 'MindNode', id: 1_289_197_285
|
||||
mas 'Keepa', id: 1_533_805_339
|
||||
mas 'MeetingBar', id: 1_532_419_400
|
||||
mas 'Pocket', id: 568_494_494
|
||||
mas 'Reeder 3', id: 880_001_334
|
||||
mas 'Spark', id: 1_176_895_641
|
||||
mas 'Tailscale', id: 1_475_387_142
|
||||
mas 'TestFlight', id: 899_247_664
|
||||
mas 'Textual 7', id: 1_262_957_439
|
||||
mas 'Things 3', id: 904_280_696
|
||||
mas 'Twitter', id: 1_482_454_543
|
||||
mas 'WireGuard', id: 1_451_685_025
|
||||
mas 'feedly', id: 865_500_966
|
||||
|
||||
# Safari Extensions
|
||||
mas 'AdGuard for Safari', id: 1_440_147_259
|
||||
mas 'Adguard for Safari', id: 1_440_147_259
|
||||
mas 'Cascadea', id: 1_432_182_561
|
||||
mas 'Dark Reader for Safari', id: 1_438_243_180
|
||||
mas 'Evernote Web Clipper', id: 1_481_669_779
|
||||
mas 'Octotree Pro', id: 1_457_450_145
|
||||
mas 'Save to Pocket', id: 1_477_385_213
|
||||
mas 'Notion Web Clipper', id: 1_559_269_364
|
||||
mas 'OctoLinkter', id: 1_549_308_269
|
||||
mas 'xSearch for Safari', id: 1_579_902_068
|
||||
end
|
||||
|
||||
# hati
|
||||
if hostname == 'hati'
|
||||
brew 'grafana'
|
||||
brew 'influxdb'
|
||||
brew 'mariadb'
|
||||
brew 'node_exporter'
|
||||
brew 'prometheus'
|
||||
|
||||
tap 'int128/kubelogin'
|
||||
brew 'kubelogin'
|
||||
|
||||
tap 'jimeh/macos-battery-exporter'
|
||||
brew 'macos-battery-exporter'
|
||||
|
||||
cask 'obsidian'
|
||||
cask 'setapp'
|
||||
cask 'teamspeak-client'
|
||||
|
||||
mas 'MeetingBar', id: 1_532_419_400
|
||||
mas 'Tailscale', id: 1_475_387_142
|
||||
end
|
||||
|
||||
61
CLAUDE.md
Normal file
61
CLAUDE.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with
|
||||
code in this repository.
|
||||
|
||||
## Overview
|
||||
|
||||
Personal dotfiles repository for macOS and Linux. Configuration files are
|
||||
symlinked to `$HOME` with a `.` prefix (e.g., `zshrc` becomes `~/.zshrc`).
|
||||
|
||||
## Commands
|
||||
|
||||
### Installation
|
||||
|
||||
```sh
|
||||
./install.sh # Install symlinks and initialize shell
|
||||
./install.sh symlinks # Only install symlinks
|
||||
./install.sh terminfo # Install terminfo entries
|
||||
./install.sh launch-agents # Install macOS LaunchAgents
|
||||
```
|
||||
|
||||
### Nix packages
|
||||
|
||||
```sh
|
||||
nix-env -if ~/.dotfiles/default.nix # Install/update global Nix packages
|
||||
nix flake update # Update nixpkgs lock
|
||||
```
|
||||
|
||||
### Hammerspoon
|
||||
|
||||
```sh
|
||||
cd hammerspoon && make install # Fetch Spoons and dependencies
|
||||
cd hammerspoon && make update # Update all dependencies
|
||||
```
|
||||
|
||||
## Structure
|
||||
|
||||
- `install.sh` - Main installer, manages symlinks to `$HOME`
|
||||
- `flake.nix` / `default.nix` - Nix package management (nixfmt, nil LSP)
|
||||
- `zshrc` / `zshenv` / `zprofile` - ZSH configuration entry points
|
||||
- `zsh/` - Modular ZSH configs loaded by topic (aliases, kubernetes, golang,
|
||||
etc.)
|
||||
- `zsh/zshrc.funcs.zsh` - Helper functions used throughout ZSH config
|
||||
- `bin/` - Personal scripts added to PATH
|
||||
- `config/` - XDG config files (ghostty, kitty, mise, starship, etc.)
|
||||
- `hammerspoon/` - macOS automation with Hammerspoon
|
||||
- `tmux/` - Tmux config and plugins (git submodules)
|
||||
- `private/` - Private dotfiles (separate repo, gitignored)
|
||||
|
||||
## Shell Setup
|
||||
|
||||
- Uses [zinit](https://github.com/zdharma-continuum/zinit) for ZSH plugin
|
||||
management
|
||||
- Uses [mise](https://mise.jdx.dev/) for runtime version management
|
||||
- Uses [starship](https://starship.rs/) for prompt
|
||||
- PATH construction happens in `zshenv`, interactive setup in `zshrc`
|
||||
|
||||
## Code Style
|
||||
|
||||
Shell scripts: 2-space indent, bash-style (see `.editorconfig` for shfmt
|
||||
settings).
|
||||
265
alacritty.toml
Normal file
265
alacritty.toml
Normal file
@@ -0,0 +1,265 @@
|
||||
[colors.normal]
|
||||
black = "#000000"
|
||||
red = "#cf5041"
|
||||
green = "#8bba48"
|
||||
yellow = "#c3a643"
|
||||
blue = "#37689f"
|
||||
magenta = "#9b589d"
|
||||
cyan = "#69b8cb"
|
||||
white = "#cccccc"
|
||||
|
||||
[colors.bright]
|
||||
black = "#686a66"
|
||||
red = "#ed3a2c"
|
||||
green = "#96cf4d"
|
||||
yellow = "#fdeb61"
|
||||
blue = "#5696d5"
|
||||
magenta = "#9d6aa5"
|
||||
cyan = "#75cee3"
|
||||
white = "#f5f5f5"
|
||||
|
||||
[colors.dim]
|
||||
black = "#333333"
|
||||
red = "#f2777a"
|
||||
green = "#99cc99"
|
||||
yellow = "#ffcc66"
|
||||
blue = "#6699cc"
|
||||
magenta = "#cc99cc"
|
||||
cyan = "#66cccc"
|
||||
white = "#dddddd"
|
||||
|
||||
[colors.primary]
|
||||
background = "#000000"
|
||||
foreground = "#D0D0D0"
|
||||
|
||||
[colors.selection]
|
||||
background = "#7499c7"
|
||||
text = "#000000"
|
||||
|
||||
[env]
|
||||
TERM = "xterm-256color"
|
||||
|
||||
[font]
|
||||
size = 12.0
|
||||
|
||||
[font.glyph_offset]
|
||||
x = 0
|
||||
y = 0
|
||||
|
||||
[font.normal]
|
||||
family = "Menlo Nerd Font"
|
||||
|
||||
[font.offset]
|
||||
x = 0
|
||||
y = 0
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "Paste"
|
||||
key = "Paste"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "Copy"
|
||||
key = "Copy"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "ClearLogNotice"
|
||||
key = "L"
|
||||
mods = "Control"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "ScrollPageUp"
|
||||
key = "PageUp"
|
||||
mode = "~Alt"
|
||||
mods = "Shift"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "ScrollPageDown"
|
||||
key = "PageDown"
|
||||
mode = "~Alt"
|
||||
mods = "Shift"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "ScrollToTop"
|
||||
key = "Home"
|
||||
mode = "~Alt"
|
||||
mods = "Shift"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "ScrollToBottom"
|
||||
key = "End"
|
||||
mode = "~Alt"
|
||||
mods = "Shift"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "SearchConfirm"
|
||||
key = "Return"
|
||||
mode = "Search|Vi"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "SearchCancel"
|
||||
key = "Escape"
|
||||
mode = "Search"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "SearchCancel"
|
||||
key = "C"
|
||||
mode = "Search"
|
||||
mods = "Control"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "SearchClear"
|
||||
key = "U"
|
||||
mode = "Search"
|
||||
mods = "Control"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "SearchDeleteWord"
|
||||
key = "W"
|
||||
mode = "Search"
|
||||
mods = "Control"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "SearchHistoryPrevious"
|
||||
key = "P"
|
||||
mode = "Search"
|
||||
mods = "Control"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "SearchHistoryNext"
|
||||
key = "N"
|
||||
mode = "Search"
|
||||
mods = "Control"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "SearchHistoryPrevious"
|
||||
key = "Up"
|
||||
mode = "Search"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "SearchHistoryNext"
|
||||
key = "Down"
|
||||
mode = "Search"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "SearchFocusNext"
|
||||
key = "Return"
|
||||
mode = "Search|~Vi"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "SearchFocusPrevious"
|
||||
key = "Return"
|
||||
mode = "Search|~Vi"
|
||||
mods = "Shift"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
chars = "\u0011"
|
||||
key = "Q"
|
||||
mods = "Control"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "ResetFontSize"
|
||||
key = "Key0"
|
||||
mods = "Command"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "IncreaseFontSize"
|
||||
key = "Equals"
|
||||
mods = "Command"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "IncreaseFontSize"
|
||||
key = "Plus"
|
||||
mods = "Command"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "IncreaseFontSize"
|
||||
key = "NumpadAdd"
|
||||
mods = "Command"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "DecreaseFontSize"
|
||||
key = "Minus"
|
||||
mods = "Command"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "DecreaseFontSize"
|
||||
key = "NumpadSubtract"
|
||||
mods = "Command"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "Paste"
|
||||
key = "V"
|
||||
mods = "Command"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "Copy"
|
||||
key = "C"
|
||||
mods = "Command"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "Hide"
|
||||
key = "H"
|
||||
mods = "Command"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "HideOtherApplications"
|
||||
key = "H"
|
||||
mods = "Command|Alt"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "Minimize"
|
||||
key = "M"
|
||||
mods = "Command"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "Quit"
|
||||
key = "Q"
|
||||
mods = "Command"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "Quit"
|
||||
key = "W"
|
||||
mods = "Command"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "SpawnNewInstance"
|
||||
key = "N"
|
||||
mods = "Command"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "ToggleSimpleFullscreen"
|
||||
key = "Return"
|
||||
mods = "Command"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "SearchForward"
|
||||
key = "F"
|
||||
mode = "~Search"
|
||||
mods = "Command"
|
||||
|
||||
[[keyboard.bindings]]
|
||||
action = "SearchBackward"
|
||||
key = "G"
|
||||
mode = "~Search"
|
||||
mods = "Command"
|
||||
|
||||
[[mouse.bindings]]
|
||||
action = "PasteSelection"
|
||||
mode = "~Vi"
|
||||
mouse = "Middle"
|
||||
|
||||
[scrolling]
|
||||
history = 50000
|
||||
multiplier = 3
|
||||
|
||||
[window]
|
||||
decorations = "full"
|
||||
dynamic_padding = true
|
||||
|
||||
[window.dimensions]
|
||||
columns = 80
|
||||
lines = 24
|
||||
|
||||
[window.padding]
|
||||
x = 2
|
||||
y = 2
|
||||
@@ -112,7 +112,7 @@ font:
|
||||
# - (macOS) Menlo
|
||||
# - (Linux/BSD) monospace
|
||||
# - (Windows) Consolas
|
||||
family: Menlo for Powerline
|
||||
family: Menlo Nerd Font Mono
|
||||
|
||||
# The `style` can be specified to pick a specific face.
|
||||
#style: Regular
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
#! /usr/bin/env ruby
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
ARGV.each do |path|
|
||||
print "Checking \"#{path}\"... "
|
||||
|
||||
if !File.exists?(path)
|
||||
puts "FILE NOT FOUND"
|
||||
unless File.exist?(path)
|
||||
puts 'FILE NOT FOUND'
|
||||
next
|
||||
end
|
||||
|
||||
checksum = `crc32 "#{path}"`.strip.upcase
|
||||
checksum = `crc32 "#{path}"`.strip.split(' ', 2).first.upcase
|
||||
if File.basename(path).upcase.include?(checksum)
|
||||
puts "MATCH (#{checksum})"
|
||||
else
|
||||
|
||||
27
bin/ffc
Executable file
27
bin/ffc
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# ffc - Files for ChatGPT
|
||||
|
||||
# Check if any arguments are provided
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Usage: $0 <file1> <file2> ... <fileN>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
shopt -s globstar nullglob
|
||||
|
||||
# Iterate over provided arguments
|
||||
for file_pattern in "$@"; do
|
||||
# Use shell expansion to find matching files
|
||||
for file in ./$file_pattern; do
|
||||
if [ -f "$file" ]; then
|
||||
rel_file="${file#./}"
|
||||
echo '`'"$rel_file"'`:'
|
||||
echo '```'
|
||||
cat "$file"
|
||||
echo '```'
|
||||
echo
|
||||
fi
|
||||
done
|
||||
done
|
||||
194
bin/generate-nerdfonts
Executable file
194
bin/generate-nerdfonts
Executable file
@@ -0,0 +1,194 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
show-help() {
|
||||
echo "Usage: $(basename "$0") [<options>] <font-patcher-script-path>" \
|
||||
"<output-dir> [<font-sources>]"
|
||||
echo ""
|
||||
echo "Generates Nerd Fonts from source fonts."
|
||||
echo ""
|
||||
echo "By default generates Nerd Font, Nerd Font Mono and Nerd Font Propo"
|
||||
echo "variants for all font files."
|
||||
echo ""
|
||||
echo "Arguments:"
|
||||
echo " <font-patcher-script-path> Path to font-patcher script"
|
||||
echo " <output-dir> Output directory for generated fonts"
|
||||
echo " <font-sources> Optional one or more font sources." \
|
||||
"Can be directories or files (default: current directory)"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --normal, -n / --no-normal Generate only/skip Nerd Font variant"
|
||||
echo " --mono, -m / --no-mono Generate only/skip Nerd Font Mono variant"
|
||||
echo " --propo, -p / --no-prop Generate only/skip Nerd Font Propo variant"
|
||||
echo " --help, -h Show this help message"
|
||||
}
|
||||
|
||||
main() {
|
||||
local args=()
|
||||
local generate_normal="1"
|
||||
local generate_mono="1"
|
||||
local generate_propo="1"
|
||||
|
||||
# Parsing flags
|
||||
while [[ "$#" -gt 0 ]]; do
|
||||
case $1 in
|
||||
--help | -h)
|
||||
show-help
|
||||
exit 0
|
||||
;;
|
||||
--normal | -n)
|
||||
generate_normal="1"
|
||||
generate_mono=""
|
||||
generate_propo=""
|
||||
;;
|
||||
--no-normal) generate_normal="" ;;
|
||||
--mono | -m)
|
||||
generate_mono="1"
|
||||
generate_normal=""
|
||||
generate_propo=""
|
||||
;;
|
||||
--no-mono) generate_mono="" ;;
|
||||
--propo | -p)
|
||||
generate_propo="1"
|
||||
generate_normal=""
|
||||
generate_mono=""
|
||||
;;
|
||||
--no-propo) generate_propo="" ;;
|
||||
--* | -?)
|
||||
echo "Unknown option: $1"
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
args+=("$1")
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
local patcher="${args[0]}"
|
||||
local outputDir="${args[1]}"
|
||||
local input_sources=("${args[@]:2}")
|
||||
local sources=()
|
||||
|
||||
if [[ -z "$patcher" || -z "$outputDir" ]]; then
|
||||
show-help 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "$generate_normal" && -z "$generate_mono" && -z "$generate_propo" ]]; then
|
||||
error "No Nerd Font variants selected."
|
||||
show-help 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
patcher="$(abs_path "$patcher")"
|
||||
if [[ ! -f "$patcher" ]]; then
|
||||
fatal "Font patcher script not found: $patcher" 1>&2
|
||||
fi
|
||||
|
||||
if ! command -v fontforge > /dev/null; then
|
||||
fatal "fontforge is not installed. Please install it first."
|
||||
fi
|
||||
|
||||
if [[ ! -d "$outputDir" ]]; then
|
||||
mkdir -p "$outputDir"
|
||||
fi
|
||||
|
||||
if [[ ${#input_sources[@]} -eq 0 ]]; then
|
||||
echo "===> No sources specified, searching for font files in current directory"
|
||||
while read -r line; do
|
||||
sources+=("$line")
|
||||
done < <(find-sources "$(abs_path "$(pwd)")")
|
||||
echo "===> Found ${#sources[@]} font files:"
|
||||
for src in "${sources[@]}"; do
|
||||
echo "---> - $src"
|
||||
done
|
||||
fi
|
||||
|
||||
for item in "${input_sources[@]}"; do
|
||||
if [[ -d $item ]]; then
|
||||
echo "===> Finding for font files in ${item}:"
|
||||
# If it's a directory, find sources and add to array
|
||||
while read -r line; do
|
||||
echo "---> - $line"
|
||||
sources+=("$line")
|
||||
done < <(find-sources "$item")
|
||||
else
|
||||
# If it's not a directory, process with abs_path and add to array
|
||||
sources+=("$(abs_path "$item")")
|
||||
fi
|
||||
done
|
||||
|
||||
# abort if no sources found
|
||||
if [[ ${#sources[@]} -eq 0 ]]; then
|
||||
error "No font files found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for src in "${sources[@]}"; do
|
||||
echo "===> Processing $src"
|
||||
|
||||
# Nerd Font
|
||||
if [[ -n "$generate_normal" ]]; then
|
||||
echo "===> Generating Nerd Font for $src"
|
||||
fontforge -lang=py -script "$patcher" --adjust-line-height --complete \
|
||||
-out "$outputDir" "$src"
|
||||
fi
|
||||
|
||||
# Nerd Font Mono
|
||||
if [[ -n "$generate_mono" ]]; then
|
||||
echo "===> Generating Nerd Font Mono for $src"
|
||||
fontforge -lang=py -script "$patcher" --adjust-line-height --complete \
|
||||
--mono \
|
||||
-out "$outputDir" "$src"
|
||||
fi
|
||||
|
||||
# Nerd Font Propo
|
||||
if [[ -n "$generate_propo" ]]; then
|
||||
echo "===> Generating Nerd Font Propo for $src"
|
||||
fontforge -lang=py -script "$patcher" --adjust-line-height --complete \
|
||||
--variable-width-glyphs \
|
||||
-out "$outputDir" "$src"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
error() {
|
||||
echo "ERROR: $1" 1>&2
|
||||
}
|
||||
|
||||
fatal() {
|
||||
error "$1"
|
||||
exit 2
|
||||
}
|
||||
|
||||
find-sources() {
|
||||
local dir="$1"
|
||||
find "$dir" -type f \( -iname '*.ttf' -o -iname '*.otf' -o -iname '*.ttc' \)
|
||||
}
|
||||
|
||||
abs_dirname() {
|
||||
local path="$1"
|
||||
local cwd
|
||||
cwd="$(pwd)"
|
||||
|
||||
while [ -n "$path" ]; do
|
||||
cd "${path%/*}" 2> /dev/null
|
||||
local name="${path##*/}"
|
||||
path="$(resolve_link "$name" || true)"
|
||||
done
|
||||
|
||||
pwd
|
||||
cd "$cwd"
|
||||
}
|
||||
|
||||
abs_path() {
|
||||
local path="$1"
|
||||
echo "$(cd "$(abs_dirname "$path")" && pwd)/$(basename "$path")"
|
||||
}
|
||||
|
||||
resolve_link() {
|
||||
$(type -p greadlink readlink | head -1) "$1"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
52
bin/gh-git-credential-helper
Executable file
52
bin/gh-git-credential-helper
Executable file
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Git credential helper that uses GitHub CLI (gh) for authentication.
|
||||
# Falls back through multiple installation methods to find gh.
|
||||
|
||||
# Enable debug logging with GH_CREDENTIAL_DEBUG=1
|
||||
debug() {
|
||||
if [[ "${GH_CREDENTIAL_DEBUG:-}" == "1" ]]; then
|
||||
echo "DEBUG: $*" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
# Show help if requested
|
||||
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
||||
cat >&2 << 'EOF'
|
||||
Git credential helper for GitHub CLI (gh)
|
||||
|
||||
This script attempts to use 'gh auth git-credential' through various
|
||||
installation methods:
|
||||
1. gh in PATH
|
||||
2. gh via mise tool manager
|
||||
3. gh via mise in ~/.local/bin/mise
|
||||
4. gh via mise shims
|
||||
|
||||
Environment variables:
|
||||
GH_CREDENTIAL_DEBUG=1 Enable debug output
|
||||
|
||||
Configuration example for .gitconfig:
|
||||
[credential "https://github.com"]
|
||||
helper = !gh-git-credential-helper
|
||||
[credential "https://gist.github.com"]
|
||||
helper = !gh-git-credential-helper
|
||||
EOF
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if command -v gh > /dev/null 2>&1; then
|
||||
debug "Using gh from PATH"
|
||||
exec gh auth git-credential "$@"
|
||||
elif command -v mise > /dev/null 2>&1; then
|
||||
debug "Using gh via mise from PATH"
|
||||
exec mise x gh -- gh auth git-credential "$@"
|
||||
elif [ -f "${HOME}/.local/bin/mise" ]; then
|
||||
debug "Using gh via mise from ~/.local/bin/mise"
|
||||
exec "${HOME}/.local/bin/mise" x gh -- gh auth git-credential "$@"
|
||||
elif [ -f "${HOME}/.local/share/mise/shims/gh" ]; then
|
||||
debug "Using gh from mise shims"
|
||||
exec "${HOME}/.local/share/mise/shims/gh" auth git-credential "$@"
|
||||
else
|
||||
echo "ERROR: GitHub CLI (gh) not found via any method" >&2
|
||||
exit 1
|
||||
fi
|
||||
@@ -13,9 +13,13 @@ show-help() {
|
||||
echo "Options:"
|
||||
echo " -p (Required) process name given to pgrep to narrow list of"
|
||||
echo " possible target windows."
|
||||
echo " -f Search full process name instead of just the first word."
|
||||
echo " -e Executable name or path used to launch process when it is not"
|
||||
echo " running. If not specified, will attempt to use process name"
|
||||
echo " instead."
|
||||
echo " -c Command used to launch process when it is not running. Can used"
|
||||
echo " instead of -e if the launch command is more complex than a"
|
||||
echo " single executable."
|
||||
echo " -w Title/name of window which belongs to process to focus on."
|
||||
echo " Allows regular expression matching. If not specified, the first"
|
||||
echo " window found belonging to process will be used."
|
||||
@@ -38,20 +42,28 @@ error-help() {
|
||||
}
|
||||
|
||||
OPT_PROC=""
|
||||
OPT_FULL=""
|
||||
OPT_BIN=""
|
||||
OPT_CMD=""
|
||||
OPT_WIN=""
|
||||
OPT_BRING=""
|
||||
OPT_ALL=""
|
||||
|
||||
parse-arguments() {
|
||||
while getopts ":p:e:w:bah" opt; do
|
||||
while getopts ":p:e:c:w:fbah" opt; do
|
||||
case ${opt} in
|
||||
p)
|
||||
OPT_PROC="$OPTARG"
|
||||
;;
|
||||
f)
|
||||
OPT_FULL="1"
|
||||
;;
|
||||
e)
|
||||
OPT_BIN="$OPTARG"
|
||||
;;
|
||||
c)
|
||||
OPT_CMD="$OPTARG"
|
||||
;;
|
||||
w)
|
||||
OPT_WIN="$OPTARG"
|
||||
;;
|
||||
@@ -63,6 +75,7 @@ parse-arguments() {
|
||||
;;
|
||||
h)
|
||||
show-help
|
||||
exit 0
|
||||
;;
|
||||
\?)
|
||||
error-help "Invalid option: -${OPTARG}\n" 1>&2
|
||||
@@ -81,7 +94,7 @@ parse-arguments() {
|
||||
OPT_BIN="$OPT_PROC"
|
||||
fi
|
||||
|
||||
if ! command -v "$OPT_BIN" &> /dev/null; then
|
||||
if [ -z "$OPT_CMD" ] && ! command -v "$OPT_BIN" &> /dev/null; then
|
||||
error "\"${OPT_BIN}\" does not seem to be a valid executable."
|
||||
exit 2
|
||||
fi
|
||||
@@ -100,8 +113,13 @@ main() {
|
||||
win_id="${target[1]}"
|
||||
|
||||
if [ -z "$pid" ]; then
|
||||
echo "$OPT_PROC not running, launching with: \"$OPT_BIN\""
|
||||
"$OPT_BIN"
|
||||
if [ -n "$OPT_CMD" ]; then
|
||||
echo "$OPT_PROC not running, launching with: \"$OPT_CMD\""
|
||||
exec $OPT_CMD
|
||||
else
|
||||
echo "$OPT_PROC not running, launching with: \"$OPT_BIN\""
|
||||
exec "$OPT_BIN"
|
||||
fi
|
||||
else
|
||||
echo "$OPT_PROC instance found"
|
||||
focused_id="$(xdotool getactivewindow)"
|
||||
@@ -130,14 +148,20 @@ find-window() {
|
||||
local pid
|
||||
local win_id
|
||||
local opts
|
||||
local pgrep_opts
|
||||
|
||||
pgrep_opts=()
|
||||
opts=(--all --onlyvisible)
|
||||
|
||||
if [ -n "$OPT_WIN" ]; then
|
||||
opts+=(--name "$OPT_WIN")
|
||||
fi
|
||||
|
||||
for pid in $(pgrep "$OPT_PROC"); do
|
||||
if [ -n "$OPT_FULL" ]; then
|
||||
pgrep_opts+=(-f)
|
||||
fi
|
||||
|
||||
for pid in $(pgrep "${pgrep_opts[@]}" "$OPT_PROC"); do
|
||||
win_id="$(xdotool search --pid "$pid" "${opts[@]}")"
|
||||
if [ -n "$win_id" ]; then
|
||||
echo -e "$pid\n$win_id"
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
#! /usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'json'
|
||||
|
||||
class MacOSBatteryExporter
|
||||
def export
|
||||
puts metrics
|
||||
end
|
||||
|
||||
def metrics
|
||||
<<~METRICS
|
||||
# HELP node_battery_charge_percent Battery charge percent
|
||||
# TYPE node_battery_charge_percent gauge
|
||||
node_battery_charge_percent{serial="#{battery_serial_number}"} #{charge_percentage}
|
||||
# HELP node_battery_charge_ampere Battery charge ampere
|
||||
# TYPE node_battery_charge_ampere gauge
|
||||
node_battery_charge_ampere{serial="#{battery_serial_number}"} #{charge_info['sppower_battery_current_capacity'] / 1000.0}
|
||||
# HELP node_battery_full_charge_ampere Battery full charge capacity
|
||||
# TYPE node_battery_full_charge_ampere gauge
|
||||
node_battery_full_charge_ampere{serial="#{battery_serial_number}"} #{charge_info['sppower_battery_max_capacity'] / 1000.0}
|
||||
# HELP node_battery_current_flow_ampere Current flow of ampere in (+) or out (-) of battery
|
||||
# TYPE node_battery_current_flow_ampere gauge
|
||||
node_battery_current_flow_ampere{serial="#{battery_serial_number}"} #{battery_info['sppower_current_amperage'] / 1000.0}
|
||||
# HELP node_battery_charger_connected Is charger connected?
|
||||
# TYPE node_battery_charger_connected gauge
|
||||
node_battery_charger_connected{serial="#{battery_serial_number}"} #{ac_charger_info['sppower_battery_charger_connected'] == 'TRUE' ? 1.0 : 0.0}
|
||||
# HELP node_battery_is_charging Is charger connected?
|
||||
# TYPE node_battery_is_charging gauge
|
||||
node_battery_is_charging{serial="#{battery_serial_number}"} #{ac_charger_info['sppower_battery_is_charging'] == 'TRUE' ? 1.0 : 0.0}
|
||||
# HELP node_battery_charger_watts Watts provided by charger
|
||||
# TYPE node_battery_charger_watts gauge
|
||||
node_battery_charger_watts{serial="#{battery_serial_number}"} #{ac_charger_info['sppower_ac_charger_watts'].to_f}
|
||||
# HELP node_battery_fully_charged Is battery fully charged?
|
||||
# TYPE node_battery_fully_charged gauge
|
||||
node_battery_fully_charged{serial="#{battery_serial_number}"} #{ac_charger_info['sppower_battery_fully_charged'] == 'TRUE' ? 1.0 : 0.0}
|
||||
# HELP node_battery_cycle_count Battery cycle count
|
||||
# TYPE node_battery_cycle_count counter
|
||||
node_battery_cycle_count{serial="#{battery_serial_number}"} #{health_info['sppower_battery_cycle_count']}
|
||||
METRICS
|
||||
end
|
||||
|
||||
def charge_percentage
|
||||
@charge_percentage ||=
|
||||
`pmset -g batt | grep -Eo '\\d+%' | cut -d% -f1`.strip
|
||||
end
|
||||
|
||||
def battery_serial_number
|
||||
battery_info.dig(
|
||||
'sppower_battery_model_info',
|
||||
'sppower_battery_serial_number'
|
||||
)
|
||||
end
|
||||
|
||||
def charge_info
|
||||
@charge_info ||= battery_info['sppower_battery_charge_info']
|
||||
end
|
||||
|
||||
def health_info
|
||||
@health_info ||= battery_info['sppower_battery_health_info']
|
||||
end
|
||||
|
||||
def battery_info
|
||||
@battery_info ||= power_data&.find do |v|
|
||||
v['_name'] == 'spbattery_information'
|
||||
end
|
||||
end
|
||||
|
||||
def ac_charger_info
|
||||
@ac_charger_info ||= power_data&.find do |v|
|
||||
v['_name'] == 'sppower_ac_charger_information'
|
||||
end
|
||||
end
|
||||
|
||||
def power_data
|
||||
@power_data ||= JSON.parse(`system_profiler SPPowerDataType -json`)
|
||||
&.[]('SPPowerDataType')
|
||||
end
|
||||
end
|
||||
|
||||
MacOSBatteryExporter.new.export if __FILE__ == $PROGRAM_NAME
|
||||
60
bin/ollama-for-gitbutler
Executable file
60
bin/ollama-for-gitbutler
Executable file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Defaults
|
||||
DEFAULT_BIND="127.0.0.1"
|
||||
DEFAULT_PORT="11435"
|
||||
DEFAULT_ORIGINS="*"
|
||||
DEFAULT_KEEP_ALIVE="6h"
|
||||
|
||||
print-help() {
|
||||
cat <<EOF
|
||||
Usage: ollama-for-gitbutler [options]
|
||||
|
||||
Options:
|
||||
-b, --bind <addr> The address to bind to (default: "${DEFAULT_BIND}")
|
||||
-p, --port <port> The port to listen on (default: "${DEFAULT_PORT}")
|
||||
-m, --models <dir> Override ollama's default models directory
|
||||
-k, --keep-alive <duration> The duration that models stay loaded in memory (default: "${DEFAULT_KEEP_ALIVE}")
|
||||
-h, --help Print this help message
|
||||
EOF
|
||||
}
|
||||
|
||||
BIND="${DEFAULT_BIND}"
|
||||
PORT="${DEFAULT_PORT}"
|
||||
KEEP_ALIVE="${DEFAULT_KEEP_ALIVE}"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-b | --bind)
|
||||
BIND="$2"
|
||||
shift 2
|
||||
;;
|
||||
-p | --port)
|
||||
PORT="$2"
|
||||
shift 2
|
||||
;;
|
||||
-m | --models)
|
||||
export OLLAMA_MODELS="$2"
|
||||
shift 2
|
||||
;;
|
||||
-k | --keep-alive)
|
||||
KEEP_ALIVE="$2"
|
||||
shift 2
|
||||
;;
|
||||
-h | --help)
|
||||
print-help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1" >&2
|
||||
print-help >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
export OLLAMA_HOST="${BIND}:${PORT}"
|
||||
export OLLAMA_KEEP_ALIVE="${KEEP_ALIVE}"
|
||||
export OLLAMA_ORIGINS="${DEFAULT_ORIGINS}"
|
||||
|
||||
exec ollama serve "$@"
|
||||
69
bin/ollama-for-obsidian
Executable file
69
bin/ollama-for-obsidian
Executable file
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Defaults
|
||||
DEFAULT_BIND="127.0.0.1"
|
||||
DEFAULT_PORT="11439"
|
||||
DEFAULT_ORIGINS="app://obsidian.md*"
|
||||
DEFAULT_KEEP_ALIVE="1h"
|
||||
|
||||
print-help() {
|
||||
cat << EOF
|
||||
Usage: ollama-for-obsidian [options]
|
||||
|
||||
Options:
|
||||
-b, --bind <addr> The address to bind to (default: "${DEFAULT_BIND}")
|
||||
-p, --port <port> The port to listen on (default: "${DEFAULT_PORT}")
|
||||
-o, --origins <origins> A comma separated list of extra allowed origins
|
||||
-m, --models <dir> Override ollama's default models directory
|
||||
-k, --keep-alive <duration> The duration that models stay loaded in memory (default: "${DEFAULT_KEEP_ALIVE}")
|
||||
-h, --help Print this help message
|
||||
EOF
|
||||
}
|
||||
|
||||
BIND="${DEFAULT_BIND}"
|
||||
PORT="${DEFAULT_PORT}"
|
||||
EXTRA_ORIGINS=""
|
||||
KEEP_ALIVE="${DEFAULT_KEEP_ALIVE}"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-b | --bind)
|
||||
BIND="$2"
|
||||
shift 2
|
||||
;;
|
||||
-p | --port)
|
||||
PORT="$2"
|
||||
shift 2
|
||||
;;
|
||||
-o | --origins)
|
||||
EXTRA_ORIGINS="$2"
|
||||
shift 2
|
||||
;;
|
||||
-m | --models)
|
||||
export OLLAMA_MODELS="$2"
|
||||
shift 2
|
||||
;;
|
||||
-k | --keep-alive)
|
||||
KEEP_ALIVE="$2"
|
||||
shift 2
|
||||
;;
|
||||
-h | --help)
|
||||
print-help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1" >&2
|
||||
print-help >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
export OLLAMA_HOST="${BIND}:${PORT}"
|
||||
export OLLAMA_KEEP_ALIVE="${KEEP_ALIVE}"
|
||||
export OLLAMA_ORIGINS="${DEFAULT_ORIGINS}"
|
||||
if [[ -n "${EXTRA_ORIGINS}" ]]; then
|
||||
export OLLAMA_ORIGINS="${OLLAMA_ORIGINS},${EXTRA_ORIGINS}"
|
||||
fi
|
||||
|
||||
exec ollama serve "$@"
|
||||
177
bin/png2icns
Executable file
177
bin/png2icns
Executable file
@@ -0,0 +1,177 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
echo "Usage: $(basename "$0") <source.png> [output.icns]" >&2
|
||||
}
|
||||
|
||||
gen-png() {
|
||||
local src="$1"
|
||||
local px="$2"
|
||||
local dpi="$3"
|
||||
local out="$4"
|
||||
|
||||
# Resize longest side to <px>, then pad to a square <px>x<px> with transparency.
|
||||
local tmp_resized
|
||||
tmp_resized="${out}.tmp.png"
|
||||
|
||||
# Scale preserving aspect ratio; longest side becomes <px>.
|
||||
sips -Z "$px" "$src" --out "$tmp_resized" > /dev/null
|
||||
|
||||
# Pad to exact square dimensions centered on transparent background.
|
||||
sips --padToHeightWidth "$px" "$px" \
|
||||
"$tmp_resized" --out "$out" > /dev/null
|
||||
|
||||
rm -f "$tmp_resized" || true
|
||||
|
||||
# Set DPI metadata.
|
||||
sips -s dpiHeight "$dpi" -s dpiWidth "$dpi" "$out" > /dev/null
|
||||
}
|
||||
|
||||
get-image-max-dim() {
|
||||
local src="$1"
|
||||
local w h
|
||||
|
||||
# Capture width/height; avoid exiting on failure due to set -e/pipefail.
|
||||
w=$(sips -g pixelWidth "$src" 2> /dev/null |
|
||||
awk '/pixelWidth/ {print $2}') || true
|
||||
h=$(sips -g pixelHeight "$src" 2> /dev/null |
|
||||
awk '/pixelHeight/ {print $2}') || true
|
||||
|
||||
if [[ -z "$w" || -z "$h" ]]; then
|
||||
echo "Failed to read image dimensions with sips: $src" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ((w > h)); then
|
||||
echo "$w"
|
||||
else
|
||||
echo "$h"
|
||||
fi
|
||||
}
|
||||
|
||||
verify-png() {
|
||||
local src="$1"
|
||||
local fmt
|
||||
fmt=$(sips -g format "$src" 2> /dev/null |
|
||||
awk '/format/ {print tolower($2)}') || true
|
||||
if [[ -z "$fmt" ]]; then
|
||||
echo "Unable to determine image format with sips: $src" >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ "$fmt" != "png" ]]; then
|
||||
echo "Input must be a PNG image: $src" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
make-iconset() {
|
||||
local src="$1"
|
||||
local dest_dir="$2"
|
||||
|
||||
mkdir -p "$dest_dir"
|
||||
|
||||
# Sizes to generate (@1x). @2x files are double the pixels.
|
||||
local sizes=(16 32 128 256 512)
|
||||
|
||||
# Determine maximum source dimension to avoid upscaling.
|
||||
local src_max
|
||||
if ! src_max=$(get-image-max-dim "$src"); then
|
||||
return 1
|
||||
fi
|
||||
|
||||
local generated
|
||||
generated=0
|
||||
|
||||
for sz in "${sizes[@]}"; do
|
||||
# @1x
|
||||
local out1="${dest_dir}/icon_${sz}x${sz}.png"
|
||||
if ((sz <= src_max)); then
|
||||
gen-png "$src" "$sz" 72 "$out1"
|
||||
generated=$((generated + 1))
|
||||
fi
|
||||
|
||||
# @2x (double pixels, higher DPI)
|
||||
local dsz=$((sz * 2))
|
||||
local out2="${dest_dir}/icon_${sz}x${sz}@2x.png"
|
||||
if ((dsz <= src_max)); then
|
||||
gen-png "$src" "$dsz" 144 "$out2"
|
||||
generated=$((generated + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
if ((generated == 0)); then
|
||||
echo "Source image too small; no icon sizes generated: $src" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
local path="$1"
|
||||
|
||||
if [[ -z "$path" || ! -d "$path" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Remove generated PNGs inside the temp directory
|
||||
find "$path" -type f -name '*.png' -delete 2> /dev/null || true
|
||||
|
||||
# Remove generated `*.iconset` inside the temp directory
|
||||
find "$path" -type d -name '*.iconset' -delete 2> /dev/null || true
|
||||
|
||||
# Attempt to remove the temp directory if now empty
|
||||
rmdir "$path" 2> /dev/null || true
|
||||
}
|
||||
|
||||
main() {
|
||||
if [[ $# -lt 1 || $# -gt 2 ]]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local src="$1"
|
||||
local out="${2:-${src%.*}.icns}"
|
||||
|
||||
if [[ ! -f "$src" ]]; then
|
||||
echo "Source file not found: $src" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v sips > /dev/null 2>&1; then
|
||||
echo "This script requires 'sips' (macOS) but it wasn't found." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v iconutil > /dev/null 2>&1; then
|
||||
echo "This script requires 'iconutil' (macOS) but it wasn't found." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local outdir
|
||||
outdir="$(dirname "$out")"
|
||||
mkdir -p "$outdir"
|
||||
|
||||
# Create a temporary working directory
|
||||
tmp_root="$(mktemp -d 2> /dev/null || mktemp -d -t png2icns)"
|
||||
trap 'cleanup "$tmp_root"' EXIT
|
||||
|
||||
# Verify input is PNG; we do not accept other formats.
|
||||
if ! verify-png "$src"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local iconset_dir
|
||||
iconset_dir="${tmp_root}/icon.iconset"
|
||||
|
||||
make-iconset "$src" "$iconset_dir"
|
||||
|
||||
# Build `.icns` from the generated iconset
|
||||
if ! iconutil -c icns -o "$out" "$iconset_dir" 2> /dev/null; then
|
||||
echo "Failed to create .icns with iconutil" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Done. ICNS written to: $out"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
461
bin/pngs2collage
Executable file
461
bin/pngs2collage
Executable file
@@ -0,0 +1,461 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
cat >&2 << EOF
|
||||
Usage: $(basename "$0") [OPTIONS] <input1.png> <input2.png> [input3.png ...]
|
||||
|
||||
Create a grid collage from multiple PNG images.
|
||||
|
||||
OPTIONS:
|
||||
-o, --output <file> Output filename (default: collage.png)
|
||||
--max-width <pixels> Maximum width for grid cells (default: 1024)
|
||||
--max-height <pixels> Maximum height for grid cells (default: 1024)
|
||||
--gap <pixels> Gap between images (default: 0)
|
||||
--border <pixels> Border around entire collage (default: 0)
|
||||
--max-columns <count> Maximum columns in grid (default: auto)
|
||||
--dpi <value> DPI for output image (default: 72)
|
||||
-h, --help Show this help message
|
||||
|
||||
ARGUMENTS:
|
||||
At least 2 input PNG files are required.
|
||||
|
||||
EXAMPLES:
|
||||
$(basename "$0") img1.png img2.png
|
||||
$(basename "$0") -o output.png --gap 10 img1.png img2.png img3.png
|
||||
$(basename "$0") --output result.png --max-columns 3 *.png
|
||||
EOF
|
||||
}
|
||||
|
||||
verify-png() {
|
||||
local src="$1"
|
||||
local fmt
|
||||
fmt=$(sips -g format "$src" 2> /dev/null |
|
||||
awk '/format/ {print tolower($2)}') || true
|
||||
if [[ -z "$fmt" ]]; then
|
||||
echo "Unable to determine image format with sips: $src" >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ "$fmt" != "png" ]]; then
|
||||
echo "Input must be a PNG image: $src" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
get-image-dimensions() {
|
||||
local src="$1"
|
||||
local w h
|
||||
|
||||
w=$(sips -g pixelWidth "$src" 2> /dev/null |
|
||||
awk '/pixelWidth/ {print $2}') || true
|
||||
h=$(sips -g pixelHeight "$src" 2> /dev/null |
|
||||
awk '/pixelHeight/ {print $2}') || true
|
||||
|
||||
if [[ -z "$w" || -z "$h" ]]; then
|
||||
echo "Failed to read image dimensions with sips: $src" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "$w $h"
|
||||
}
|
||||
|
||||
calculate-cell-size() {
|
||||
local max_w="$1"
|
||||
local max_h="$2"
|
||||
shift 2
|
||||
local images=("$@")
|
||||
|
||||
local cell_w=0
|
||||
local cell_h=0
|
||||
local any_exceeds=0
|
||||
|
||||
for img in "${images[@]}"; do
|
||||
local dims
|
||||
if ! dims=$(get-image-dimensions "$img"); then
|
||||
return 1
|
||||
fi
|
||||
local w h
|
||||
read -r w h <<< "$dims"
|
||||
|
||||
if ((w > max_w || h > max_h)); then
|
||||
any_exceeds=1
|
||||
fi
|
||||
|
||||
if ((w > cell_w)); then
|
||||
cell_w=$w
|
||||
fi
|
||||
if ((h > cell_h)); then
|
||||
cell_h=$h
|
||||
fi
|
||||
done
|
||||
|
||||
# If any image exceeds max dimensions, use max dimensions as cell size
|
||||
if ((any_exceeds)); then
|
||||
if ((max_w > max_h)); then
|
||||
echo "$max_w $max_w"
|
||||
else
|
||||
echo "$max_h $max_h"
|
||||
fi
|
||||
else
|
||||
# Use largest dimension from all images to make square cells
|
||||
if ((cell_w > cell_h)); then
|
||||
echo "$cell_w $cell_w"
|
||||
else
|
||||
echo "$cell_h $cell_h"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
calculate-padding() {
|
||||
local row="$1"
|
||||
local col="$2"
|
||||
local total_rows="$3"
|
||||
local total_cols="$4"
|
||||
local gap="$5"
|
||||
local border="$6"
|
||||
|
||||
local top bottom left right
|
||||
local half_gap
|
||||
|
||||
# Calculate half gap (rounded for odd gaps)
|
||||
half_gap=$(awk "BEGIN {print int($gap / 2)}")
|
||||
|
||||
# Top padding
|
||||
if ((row == 0)); then
|
||||
top=$border
|
||||
else
|
||||
top=$half_gap
|
||||
fi
|
||||
|
||||
# Bottom padding
|
||||
if ((row == total_rows - 1)); then
|
||||
bottom=$border
|
||||
else
|
||||
bottom=$half_gap
|
||||
fi
|
||||
|
||||
# Left padding
|
||||
if ((col == 0)); then
|
||||
left=$border
|
||||
else
|
||||
left=$half_gap
|
||||
fi
|
||||
|
||||
# Right padding
|
||||
if ((col == total_cols - 1)); then
|
||||
right=$border
|
||||
else
|
||||
right=$half_gap
|
||||
fi
|
||||
|
||||
echo "$top $bottom $left $right"
|
||||
}
|
||||
|
||||
prepare-image() {
|
||||
local src="$1"
|
||||
local cell_size="$2"
|
||||
local top="$3"
|
||||
local bottom="$4"
|
||||
local left="$5"
|
||||
local right="$6"
|
||||
local out="$7"
|
||||
|
||||
local tmp_resized tmp_padded
|
||||
tmp_resized="${out}.tmp.resized.png"
|
||||
tmp_padded="${out}.tmp.padded.png"
|
||||
|
||||
# Scale preserving aspect ratio; fit within cell size
|
||||
sips -Z "$cell_size" "$src" --out "$tmp_resized" > /dev/null
|
||||
|
||||
# Pad to exact square dimensions centered on transparent background
|
||||
sips --padToHeightWidth "$cell_size" "$cell_size" \
|
||||
"$tmp_resized" --out "$tmp_padded" > /dev/null
|
||||
|
||||
# Apply asymmetric padding using ImageMagick
|
||||
# Create a transparent canvas and composite the image at the correct position
|
||||
local final_width final_height
|
||||
final_width=$((cell_size + left + right))
|
||||
final_height=$((cell_size + top + bottom))
|
||||
|
||||
# Create transparent canvas of final size, then composite the prepared
|
||||
# image at position (left, top) to create the exact padding we want
|
||||
if ! magick -size "${final_width}x${final_height}" xc:none \
|
||||
"$tmp_padded" -geometry "+${left}+${top}" -composite \
|
||||
"$out" 2> /dev/null; then
|
||||
echo "Failed to apply padding to image: $src" >&2
|
||||
rm -f "$tmp_resized" "$tmp_padded" || true
|
||||
return 1
|
||||
fi
|
||||
|
||||
rm -f "$tmp_resized" "$tmp_padded" || true
|
||||
}
|
||||
|
||||
calculate-grid-dimensions() {
|
||||
local count="$1"
|
||||
local max_cols="$2"
|
||||
|
||||
local cols rows
|
||||
|
||||
if [[ "$max_cols" == "auto" ]]; then
|
||||
# Calculate square-ish grid
|
||||
cols=$(awk "BEGIN {print int(sqrt($count) + 0.999)}")
|
||||
else
|
||||
if ((max_cols > count)); then
|
||||
cols=$count
|
||||
else
|
||||
cols=$max_cols
|
||||
fi
|
||||
fi
|
||||
|
||||
rows=$(awk "BEGIN {print int(($count + $cols - 1) / $cols)}")
|
||||
|
||||
echo "$cols $rows"
|
||||
}
|
||||
|
||||
create-collage() {
|
||||
local cols="$1"
|
||||
local rows="$2"
|
||||
local dpi="$3"
|
||||
local out="$4"
|
||||
shift 4
|
||||
local images=("$@")
|
||||
|
||||
# Build ImageMagick montage command
|
||||
# montage combines images in a grid with zero spacing
|
||||
# (padding is already applied to individual images)
|
||||
local tile_arg="${cols}x${rows}"
|
||||
|
||||
# Create collage with transparent background and zero spacing
|
||||
if ! magick montage "${images[@]}" \
|
||||
-tile "$tile_arg" \
|
||||
-geometry "+0+0" \
|
||||
-background "none" \
|
||||
"$out" 2> /dev/null; then
|
||||
echo "Failed to create collage with ImageMagick" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Set DPI metadata
|
||||
sips -s dpiHeight "$dpi" -s dpiWidth "$dpi" "$out" > /dev/null
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
local path="$1"
|
||||
|
||||
if [[ -z "$path" || ! -d "$path" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Remove generated PNGs inside the temp directory
|
||||
find "$path" -type f -name '*.png' -delete 2> /dev/null || true
|
||||
|
||||
# Attempt to remove the temp directory if now empty
|
||||
rmdir "$path" 2> /dev/null || true
|
||||
}
|
||||
|
||||
parse-args() {
|
||||
local max_width=1024
|
||||
local max_height=1024
|
||||
local gap=0
|
||||
local border=0
|
||||
local max_columns="auto"
|
||||
local dpi=72
|
||||
local output_file=""
|
||||
local -a input_files=()
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-h | --help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
-o | --output)
|
||||
output_file="$2"
|
||||
shift 2
|
||||
;;
|
||||
--max-width)
|
||||
max_width="$2"
|
||||
shift 2
|
||||
;;
|
||||
--max-height)
|
||||
max_height="$2"
|
||||
shift 2
|
||||
;;
|
||||
--gap)
|
||||
gap="$2"
|
||||
shift 2
|
||||
;;
|
||||
--border)
|
||||
border="$2"
|
||||
shift 2
|
||||
;;
|
||||
--max-columns)
|
||||
max_columns="$2"
|
||||
shift 2
|
||||
;;
|
||||
--dpi)
|
||||
dpi="$2"
|
||||
shift 2
|
||||
;;
|
||||
-*)
|
||||
echo "Unknown option: $1" >&2
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
input_files+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Export parsed values for main to access
|
||||
export PARSED_MAX_WIDTH="$max_width"
|
||||
export PARSED_MAX_HEIGHT="$max_height"
|
||||
export PARSED_GAP="$gap"
|
||||
export PARSED_BORDER="$border"
|
||||
export PARSED_MAX_COLUMNS="$max_columns"
|
||||
export PARSED_DPI="$dpi"
|
||||
export PARSED_OUTPUT="$output_file"
|
||||
export PARSED_INPUT_COUNT="${#input_files[@]}"
|
||||
|
||||
# Export input files as a string (will be parsed in main)
|
||||
local i
|
||||
for i in "${!input_files[@]}"; do
|
||||
export "PARSED_INPUT_$i=${input_files[$i]}"
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
if [[ $# -lt 2 ]]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Parse arguments
|
||||
parse-args "$@"
|
||||
|
||||
# Reconstruct input files array from exports
|
||||
local -a all_files=()
|
||||
local i
|
||||
for ((i = 0; i < PARSED_INPUT_COUNT; i++)); do
|
||||
local varname="PARSED_INPUT_$i"
|
||||
all_files+=("${!varname}")
|
||||
done
|
||||
|
||||
# Determine output file and input files
|
||||
local -a input_files=()
|
||||
local output_file
|
||||
|
||||
if [[ -n "$PARSED_OUTPUT" ]]; then
|
||||
# Explicit output was specified via --output/-o
|
||||
output_file="$PARSED_OUTPUT"
|
||||
input_files=("${all_files[@]}")
|
||||
else
|
||||
# No explicit output, use default or check last argument
|
||||
output_file="collage.png"
|
||||
if [[ ${#all_files[@]} -ge 2 ]]; then
|
||||
local last_file="${all_files[-1]}"
|
||||
# If last file doesn't exist and has .png extension, treat as output
|
||||
if [[ ! -f "$last_file" && "$last_file" == *.png ]]; then
|
||||
output_file="$last_file"
|
||||
input_files=("${all_files[@]:0:$((${#all_files[@]} - 1))}")
|
||||
else
|
||||
input_files=("${all_files[@]}")
|
||||
fi
|
||||
else
|
||||
input_files=("${all_files[@]}")
|
||||
fi
|
||||
fi
|
||||
|
||||
# Validate we have at least 2 input files
|
||||
if [[ ${#input_files[@]} -lt 2 ]]; then
|
||||
echo "Error: At least 2 input PNG files are required." >&2
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for required commands
|
||||
if ! command -v sips > /dev/null 2>&1; then
|
||||
echo "This script requires 'sips' (macOS) but it wasn't found." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v magick > /dev/null 2>&1; then
|
||||
echo "This script requires 'magick' (ImageMagick) but it wasn't found." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify all input files exist and are PNGs
|
||||
for img in "${input_files[@]}"; do
|
||||
if [[ ! -f "$img" ]]; then
|
||||
echo "Input file not found: $img" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! verify-png "$img"; then
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Create output directory if needed
|
||||
local outdir
|
||||
outdir="$(dirname "$output_file")"
|
||||
mkdir -p "$outdir"
|
||||
|
||||
# Create temporary working directory
|
||||
tmp_root="$(mktemp -d 2> /dev/null || mktemp -d -t pngs2collage)"
|
||||
trap 'cleanup "$tmp_root"' EXIT
|
||||
|
||||
# Calculate grid dimensions first
|
||||
local grid_dims
|
||||
grid_dims=$(calculate-grid-dimensions "${#input_files[@]}" \
|
||||
"$PARSED_MAX_COLUMNS")
|
||||
local cols rows
|
||||
read -r cols rows <<< "$grid_dims"
|
||||
|
||||
# Calculate cell size
|
||||
local cell_dims
|
||||
if ! cell_dims=$(calculate-cell-size "$PARSED_MAX_WIDTH" \
|
||||
"$PARSED_MAX_HEIGHT" "${input_files[@]}"); then
|
||||
exit 1
|
||||
fi
|
||||
local cell_size
|
||||
read -r cell_size _ <<< "$cell_dims"
|
||||
|
||||
# Prepare all images with position-specific padding
|
||||
local -a prepared_images=()
|
||||
local idx=0
|
||||
for img in "${input_files[@]}"; do
|
||||
# Calculate grid position (row, col) from index
|
||||
local row col
|
||||
row=$((idx / cols))
|
||||
col=$((idx % cols))
|
||||
|
||||
# Calculate padding for this position
|
||||
local padding
|
||||
padding=$(calculate-padding "$row" "$col" "$rows" "$cols" \
|
||||
"$PARSED_GAP" "$PARSED_BORDER")
|
||||
local top bottom left right
|
||||
read -r top bottom left right <<< "$padding"
|
||||
|
||||
# Prepare image with position-specific padding
|
||||
local prepared="${tmp_root}/prepared_${idx}.png"
|
||||
if ! prepare-image "$img" "$cell_size" "$top" "$bottom" "$left" \
|
||||
"$right" "$prepared"; then
|
||||
echo "Failed to prepare image: $img" >&2
|
||||
exit 1
|
||||
fi
|
||||
prepared_images+=("$prepared")
|
||||
idx=$((idx + 1))
|
||||
done
|
||||
|
||||
# Create the collage
|
||||
if ! create-collage "$cols" "$rows" "$PARSED_DPI" "$output_file" \
|
||||
"${prepared_images[@]}"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Done. Collage written to: $output_file"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
12
bin/vk
Executable file
12
bin/vk
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
export BACKEND_PORT=34802
|
||||
|
||||
if command -v vibe-kanban >/dev/null 2>&1; then
|
||||
exec vibe-kanban "$@"
|
||||
elif command -v npx >/dev/null 2>&1; then
|
||||
exec npx vibe-kanban "$@"
|
||||
else
|
||||
echo "Neither vibe-kanban nor npx is installed"
|
||||
exit 1
|
||||
fi
|
||||
78
config/ghostty/config
Normal file
78
config/ghostty/config
Normal file
@@ -0,0 +1,78 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# General settings
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
auto-update-channel = stable
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Theme settings
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
theme = tango-with-monokai
|
||||
window-theme = dark
|
||||
|
||||
background-opacity = 0.8
|
||||
background-blur-radius = 20
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Font settings
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
font-size = 12
|
||||
|
||||
font-family = Menlo Nerd Font
|
||||
font-family-bold = Menlo Nerd Font Bold
|
||||
font-family-italic = Menlo Nerd Font Italic
|
||||
font-family-bold-italic = Menlo Nerd Font Bold Italic
|
||||
|
||||
# Match font rendering of iTerm and Terminal.app.
|
||||
adjust-cell-width = -1
|
||||
font-thicken = true
|
||||
|
||||
# Disable ligatures
|
||||
font-feature = -calt
|
||||
font-feature = -dlig
|
||||
font-feature = -liga
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# macOS settings
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
macos-non-native-fullscreen = true
|
||||
macos-option-as-alt = true
|
||||
|
||||
macos-titlebar-proxy-icon = hidden
|
||||
macos-titlebar-style = transparent
|
||||
|
||||
macos-secure-input-indication = true
|
||||
macos-auto-secure-input = true
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Cursor settings
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
cursor-style = block
|
||||
shell-integration-features = no-cursor
|
||||
|
||||
mouse-hide-while-typing = true
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Window settings
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
window-padding-balance = true
|
||||
window-step-resize = true
|
||||
|
||||
# macOS notch padding: 14-inch@2704x1756
|
||||
# window-padding-y = 60,20
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Keybindings
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Clipboard (ensure super/cmd+c/v are always available, including on Linux)
|
||||
keybind = super+c=copy_to_clipboard
|
||||
keybind = super+v=paste_from_clipboard
|
||||
|
||||
# Quick Terminal (alt+`)
|
||||
keybind = global:alt+grave_accent=toggle_quick_terminal
|
||||
21
config/ghostty/themes/tango-with-monokai
Normal file
21
config/ghostty/themes/tango-with-monokai
Normal file
@@ -0,0 +1,21 @@
|
||||
palette = 0=#000000
|
||||
palette = 1=#cf5041
|
||||
palette = 2=#8bba48
|
||||
palette = 3=#c3a643
|
||||
palette = 4=#37689f
|
||||
palette = 5=#9b589d
|
||||
palette = 6=#69b8cb
|
||||
palette = 7=#cccccc
|
||||
palette = 8=#686a66
|
||||
palette = 9=#ed3a2c
|
||||
palette = 10=#96cf4d
|
||||
palette = 11=#fdeb61
|
||||
palette = 12=#5696d5
|
||||
palette = 13=#9d6aa5
|
||||
palette = 14=#75cee3
|
||||
palette = 15=#f5f5f5
|
||||
background = 000000
|
||||
foreground = ffffff
|
||||
cursor-color = D0D0D0
|
||||
selection-background = 7499c7
|
||||
selection-foreground = 000000
|
||||
File diff suppressed because it is too large
Load Diff
2648
config/kitty/kitty.defaults.conf
Normal file
2648
config/kitty/kitty.defaults.conf
Normal file
File diff suppressed because it is too large
Load Diff
22
config/kitty/themes/tango-with-monokai.conf
Normal file
22
config/kitty/themes/tango-with-monokai.conf
Normal file
@@ -0,0 +1,22 @@
|
||||
color0 #000000
|
||||
color1 #cf5041
|
||||
color2 #8bba48
|
||||
color3 #c3a643
|
||||
color4 #37689f
|
||||
color5 #9b589d
|
||||
color6 #69b8cb
|
||||
color7 #cccccc
|
||||
color8 #686a66
|
||||
color9 #ed3a2c
|
||||
color10 #96cf4d
|
||||
color11 #fdeb61
|
||||
color12 #5696d5
|
||||
color13 #9d6aa5
|
||||
color14 #75cee3
|
||||
color15 #f5f5f5
|
||||
background #000000
|
||||
foreground #ffffff
|
||||
cursor #D0D0D0
|
||||
selection_background #7499c7
|
||||
selection_foreground #000000
|
||||
url_color #0087bd
|
||||
179
config/mise/config.toml
Normal file
179
config/mise/config.toml
Normal file
@@ -0,0 +1,179 @@
|
||||
[settings]
|
||||
cargo_binstall = true
|
||||
experimental = true
|
||||
legacy_version_file = true
|
||||
not_found_auto_install = false
|
||||
idiomatic_version_file_enable_tools = [
|
||||
"ruby",
|
||||
"python",
|
||||
"node",
|
||||
"go",
|
||||
"terraform",
|
||||
"yarn",
|
||||
]
|
||||
|
||||
[settings.status]
|
||||
show_env = true
|
||||
show_tools = false
|
||||
|
||||
[settings.npm]
|
||||
bun = true
|
||||
|
||||
[settings.pipx]
|
||||
# Allow mise to install pipx packages without manual installation of pipx.
|
||||
uvx = true
|
||||
|
||||
[settings.ruby]
|
||||
# Precompiled binaries causes issues with Ruby LSP.
|
||||
compile = true
|
||||
|
||||
[tools]
|
||||
"aqua:AlexanderGrooff/mermaid-ascii" = "latest"
|
||||
"aqua:svenstaro/miniserve" = "latest"
|
||||
"aqua:tldr-pages/tlrc" = "latest"
|
||||
"cargo:bacon" = "latest"
|
||||
"cargo:cargo-audit" = "latest"
|
||||
"cargo:cargo-edit" = "latest"
|
||||
"cargo:cargo-info" = "latest"
|
||||
"cargo:cargo-show" = "latest"
|
||||
"cargo:cargo-update" = "latest"
|
||||
"cargo:dirstat-rs" = "latest"
|
||||
"cargo:dutree" = "latest"
|
||||
"cargo:eza" = "latest"
|
||||
"cargo:kubectl-watch" = "latest"
|
||||
"cargo:mergiraf" = "latest"
|
||||
"cargo:paper-terminal" = "latest"
|
||||
"cargo:parallel-disk-usage" = { version = "latest", bin = "pdu" }
|
||||
"cargo:pastel" = "latest"
|
||||
"cargo:riffdiff" = "latest"
|
||||
"github:stacklok/toolhive" = "latest"
|
||||
"go:github.com/rakyll/hey" = "latest"
|
||||
"go:google.golang.org/grpc/cmd/protoc-gen-go-grpc" = "latest"
|
||||
"go:google.golang.org/protobuf/cmd/protoc-gen-go" = "latest"
|
||||
"npm:@github/copilot-language-server" = "latest"
|
||||
"npm:@mermaid-js/mermaid-cli" = "latest"
|
||||
"npm:@openai/codex" = "latest"
|
||||
"npm:@prettier/plugin-php" = "latest"
|
||||
"npm:claude-plugins" = "latest"
|
||||
"npm:convex" = "latest"
|
||||
"npm:dockerfile-language-server-nodejs" = "latest"
|
||||
"npm:eslint" = "latest"
|
||||
"npm:eslint-config-prettier" = "latest"
|
||||
"npm:eslint-plugin-prettier" = "latest"
|
||||
"npm:eslint_d" = "latest"
|
||||
"npm:htmllint-cli" = "latest"
|
||||
"npm:http-server" = "latest"
|
||||
"npm:httpsnippet" = "latest"
|
||||
"npm:jsonlint" = "latest"
|
||||
"npm:localtunnel" = "latest"
|
||||
"npm:markdown-it" = "latest"
|
||||
"npm:oxfmt" = "latest"
|
||||
"npm:oxlint" = "latest"
|
||||
"npm:prettier" = "latest"
|
||||
"npm:prettier-plugin-toml" = "latest"
|
||||
"npm:prettier-pnp" = "latest"
|
||||
"npm:skills" = "latest"
|
||||
"npm:stylelint" = "latest"
|
||||
"npm:svgo" = "latest"
|
||||
"npm:typescript" = "latest"
|
||||
"npm:typescript-formatter" = "latest"
|
||||
"npm:typescript-language-server" = "latest"
|
||||
"npm:vscode-css-languageserver-bin" = "latest"
|
||||
"npm:vscode-json-languageserver" = "latest"
|
||||
"npm:yaml-language-server" = "latest"
|
||||
"npm:yarn" = "latest"
|
||||
"pipx:ansible-lint" = "latest"
|
||||
"pipx:dmgbuild" = "latest"
|
||||
"pipx:fonttools" = "latest"
|
||||
"pipx:pipx" = "latest"
|
||||
"pipx:toml-sort" = "latest"
|
||||
"pipx:yamllint" = "latest"
|
||||
1password = "latest"
|
||||
actionlint = "latest"
|
||||
argo-rollouts = "latest"
|
||||
argocd = "latest"
|
||||
atuin = "latest"
|
||||
aws-cli = "latest"
|
||||
bat = "latest"
|
||||
bat-extras = "latest"
|
||||
buf = "latest"
|
||||
bun = "latest"
|
||||
cargo-binstall = "latest"
|
||||
cloudflared = "latest"
|
||||
crane = "latest"
|
||||
ctop = "latest"
|
||||
difftastic = "latest"
|
||||
direnv = "latest"
|
||||
dua = "latest"
|
||||
dust = "latest"
|
||||
evans = "latest"
|
||||
fd = "latest"
|
||||
fzf = "latest"
|
||||
gemini = "latest"
|
||||
gh = "latest"
|
||||
gitu = "latest"
|
||||
go = "latest"
|
||||
gofumpt = "latest"
|
||||
golangci-lint = "latest"
|
||||
golangci-lint-langserver = "latest"
|
||||
golines = "latest"
|
||||
goreleaser = "latest"
|
||||
grpcurl = "latest"
|
||||
hadolint = "latest"
|
||||
helm = "latest"
|
||||
helmfile = "latest"
|
||||
hexyl = "latest"
|
||||
hivemind = "latest"
|
||||
hwatch = "latest"
|
||||
jq = "latest"
|
||||
jwt = "latest"
|
||||
jwtui = "latest"
|
||||
k3d = "latest"
|
||||
k9s = "latest"
|
||||
kubecm = "latest"
|
||||
kubectl = "latest"
|
||||
kubectx = "latest"
|
||||
kubelogin = "latest"
|
||||
kubens = "latest"
|
||||
kustomize = "latest"
|
||||
lua = "latest"
|
||||
lua-language-server = "latest"
|
||||
markdownlint-cli2 = "latest"
|
||||
node = "lts"
|
||||
opencode = "latest"
|
||||
opentofu = "latest"
|
||||
pnpm = "latest"
|
||||
python = "latest"
|
||||
rclone = "latest"
|
||||
restish = "latest"
|
||||
ripgrep = "latest"
|
||||
ruby = "latest"
|
||||
rust = { version = "latest", components = "rust-analyzer,rust-src" }
|
||||
sccache = "latest"
|
||||
shellcheck = "latest"
|
||||
shfmt = "latest"
|
||||
slsa-verifier = "latest"
|
||||
sops = "latest"
|
||||
starship = "latest"
|
||||
staticcheck = "latest"
|
||||
stern = "latest"
|
||||
talosctl = "latest"
|
||||
taplo = "latest"
|
||||
terraform = "latest"
|
||||
terraform-ls = "latest"
|
||||
tflint = "latest"
|
||||
ubi = "latest"
|
||||
usage = "latest"
|
||||
uv = "latest"
|
||||
watchexec = "latest"
|
||||
yj = "latest"
|
||||
yq = "latest"
|
||||
zig = "latest"
|
||||
zls = "latest"
|
||||
zoxide = "latest"
|
||||
|
||||
# Install ansible with passlib and bcrypt<4.1, as passlib is not compatible with
|
||||
# bcrypt 4.1 or later.
|
||||
[tools."pipx:ansible"]
|
||||
version = "latest"
|
||||
uvx_args = "--with-executables-from=ansible-core --with=passlib --with='bcrypt<4.1'"
|
||||
1
config/nix/nix.conf
Normal file
1
config/nix/nix.conf
Normal file
@@ -0,0 +1 @@
|
||||
experimental-features = nix-command flakes
|
||||
@@ -1,4 +1,6 @@
|
||||
---
|
||||
# plugins:
|
||||
# - solargraph-rails
|
||||
exclude:
|
||||
- ".bundle/**/*"
|
||||
- "spec/**/*"
|
||||
@@ -16,6 +18,7 @@ formatter:
|
||||
- Lint/Debugger
|
||||
- Lint/UnusedBlockArgument
|
||||
- Lint/UnusedMethodArgument
|
||||
- Rails/Output
|
||||
- Lint/UselessAssignment
|
||||
# - Rails/Output
|
||||
- Style/EmptyMethod
|
||||
- Style/Semicolon
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# jimeh's Starship Config
|
||||
# ------------------------------------------------------------------------------
|
||||
# Version: 0.1.2
|
||||
# Version: 0.5.0
|
||||
# URL: https://github.com/jimeh/dotfiles/blob/main/config/starship.toml
|
||||
# ------------------------------------------------------------------------------
|
||||
# This is minimalistic Starship (https://starship.rs/) prompt setup with most
|
||||
# features shifted to the right prompt, and disabled, allowing for easy cherry
|
||||
# picking of specific features to enable.
|
||||
# ------------------------------------------------------------------------------
|
||||
#
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# MARK: Format
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
add_newline = false
|
||||
|
||||
format = """
|
||||
$username\
|
||||
$hostname\
|
||||
@@ -20,195 +25,241 @@ $git_state\
|
||||
$git_metrics\
|
||||
$git_status\
|
||||
$hg_branch\
|
||||
$fossil_branch\
|
||||
$fossil_metrics\
|
||||
$hg_state\
|
||||
$line_break\
|
||||
$character"""
|
||||
|
||||
right_format = """
|
||||
$all\
|
||||
$localip\
|
||||
$shlvl\
|
||||
$singularity\
|
||||
$kubernetes\
|
||||
$vcsh\
|
||||
$pijul_channel\
|
||||
$docker_context\
|
||||
$package\
|
||||
$c\
|
||||
$cmake\
|
||||
$cobol\
|
||||
$crystal\
|
||||
$daml\
|
||||
$dart\
|
||||
$deno\
|
||||
$dotnet\
|
||||
$elixir\
|
||||
$elm\
|
||||
$erlang\
|
||||
$fennel\
|
||||
$fortran\
|
||||
$gleam\
|
||||
$golang\
|
||||
$guix_shell\
|
||||
$haskell\
|
||||
$haxe\
|
||||
$java\
|
||||
$julia\
|
||||
$kotlin\
|
||||
$gradle\
|
||||
$lua\
|
||||
$nim\
|
||||
$nodejs\
|
||||
$bun\
|
||||
$ocaml\
|
||||
$opa\
|
||||
$perl\
|
||||
$php\
|
||||
$pulumi\
|
||||
$purescript\
|
||||
$python\
|
||||
$red\
|
||||
$quarto\
|
||||
$raku\
|
||||
$rlang\
|
||||
$red\
|
||||
$ruby\
|
||||
$rust\
|
||||
$scala\
|
||||
$solidity\
|
||||
$swift\
|
||||
$terraform\
|
||||
$typst\
|
||||
$vlang\
|
||||
$vagrant\
|
||||
$zig\
|
||||
$aws\
|
||||
$azure\
|
||||
$buf\
|
||||
$nix_shell\
|
||||
$conda\
|
||||
$docker_context\
|
||||
$meson\
|
||||
$spack\
|
||||
$aws\
|
||||
$gcloud\
|
||||
$helm\
|
||||
$kubernetes\
|
||||
$nix_shell\
|
||||
$openstack\
|
||||
$package\
|
||||
$singularity\
|
||||
$terraform\
|
||||
$vagrant\
|
||||
$vcsh\
|
||||
$shlvl\
|
||||
$azure\
|
||||
$env_var\
|
||||
$crystal\
|
||||
$custom\
|
||||
$cmd_duration\
|
||||
$status\
|
||||
$line_break\
|
||||
$direnv\
|
||||
$mise\
|
||||
$nats\
|
||||
$jobs\
|
||||
$netns\
|
||||
$shell\
|
||||
$sudo\
|
||||
$battery\
|
||||
$memory_usage\
|
||||
$os\
|
||||
$container\
|
||||
$time"""
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Main left prompt components
|
||||
# MARK: Left prompt
|
||||
# ------------------------------------------------------------------------------
|
||||
#
|
||||
|
||||
[username]
|
||||
show_always = true
|
||||
format = "[$user]($style)"
|
||||
style_user = "fg:251"
|
||||
style_root = "bold fg:196 bg:52"
|
||||
format = '[$user]($style)'
|
||||
style_user = 'fg:251'
|
||||
style_root = 'bold fg:196 bg:52'
|
||||
|
||||
[hostname]
|
||||
ssh_only = false
|
||||
format = "([@$hostname]($style) )"
|
||||
style = "fg:251"
|
||||
format = '([@$hostname]($style) )'
|
||||
style = 'fg:251'
|
||||
|
||||
[directory]
|
||||
truncate_to_repo = false
|
||||
truncation_length = 99
|
||||
format = '[$path]($style)[$read_only]($read_only_style) '
|
||||
style = ""
|
||||
read_only = ""
|
||||
read_only_style = "bold red"
|
||||
style = ''
|
||||
read_only = ''
|
||||
read_only_style = 'bold red'
|
||||
|
||||
[line_break]
|
||||
disabled = true
|
||||
|
||||
[character]
|
||||
success_symbol = "[❯](bold fg:118)"
|
||||
error_symbol = "[❯](bold fg:46)"
|
||||
vicmd_symbol = "[❮](bold fg:46)"
|
||||
success_symbol = '[❯](bold fg:118)'
|
||||
error_symbol = '[❯](bold fg:46)'
|
||||
vimcmd_symbol = '[❮](bold fg:46)'
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Source Control
|
||||
# MARK: Source Control
|
||||
# ------------------------------------------------------------------------------
|
||||
#
|
||||
|
||||
[git_branch]
|
||||
format = '([$symbol$branch]($style))'
|
||||
style = "fg:51"
|
||||
symbol = ""
|
||||
style = 'fg:51'
|
||||
symbol = ''
|
||||
truncation_length = 24
|
||||
|
||||
[git_commit]
|
||||
tag_symbol = ""
|
||||
tag_symbol = ''
|
||||
format = '[\($hash$tag\)]($style)'
|
||||
style = "bold fg:213"
|
||||
style = 'bold fg:213'
|
||||
only_detached = true
|
||||
tag_disabled = false
|
||||
|
||||
[git_state]
|
||||
format = '\[[$state($progress_current/$progress_total)]($style)\]'
|
||||
style = "bold fg:208"
|
||||
style = 'bold fg:208'
|
||||
|
||||
[git_metrics]
|
||||
added_style = "bold fg:148"
|
||||
deleted_style = "bold fg:196"
|
||||
added_style = 'bold fg:148'
|
||||
deleted_style = 'bold fg:196'
|
||||
format = '([\[](fg:51)([+$added]($added_style))([-$deleted]($deleted_style))[\]](fg:51))'
|
||||
disabled = true
|
||||
|
||||
[git_status]
|
||||
format = '([$all_status$ahead_behind]($style)) '
|
||||
style = "bold fg:201"
|
||||
stashed = ""
|
||||
style = 'bold fg:201'
|
||||
stashed = ''
|
||||
ahead = ""
|
||||
behind = ""
|
||||
modified = "!"
|
||||
untracked = "?"
|
||||
diverged = ""
|
||||
deleted = "✖"
|
||||
behind = ''
|
||||
modified = '!'
|
||||
untracked = '?'
|
||||
diverged = ''
|
||||
deleted = '✖'
|
||||
|
||||
[hg_branch]
|
||||
format = '([$symbol$branch]($style))'
|
||||
style = "fg:51"
|
||||
symbol = ""
|
||||
style = 'fg:51'
|
||||
symbol = ''
|
||||
truncation_length = 24
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Right prompt "status" components
|
||||
# MARK: Right prompt
|
||||
# ------------------------------------------------------------------------------
|
||||
#
|
||||
|
||||
[shlvl]
|
||||
symbol = " "
|
||||
format = "( [$symbol$shlvl]($style))"
|
||||
symbol = ' '
|
||||
format = '( [$symbol$shlvl]($style))'
|
||||
disabled = true
|
||||
|
||||
[cmd_duration]
|
||||
format = '( [\(](fg:242)[$duration]($style)[\)](fg:242))'
|
||||
style = "bold fg:220"
|
||||
style = 'bold fg:220'
|
||||
|
||||
[sudo]
|
||||
symbol = " "
|
||||
format = "[$symbol]($style)"
|
||||
style = "bold dimmed red"
|
||||
symbol = ' '
|
||||
format = '[$symbol]($style)'
|
||||
style = 'bold dimmed red'
|
||||
disabled = false
|
||||
|
||||
[status]
|
||||
format = "( [$symbol$status]($style))"
|
||||
style = "bold red"
|
||||
symbol = ''
|
||||
success_symbol = ''
|
||||
not_executable_symbol = ''
|
||||
not_found_symbol = ''
|
||||
sigint_symbol = ''
|
||||
signal_symbol = ''
|
||||
format = '( [$symbol$status]($style))'
|
||||
style = 'bold red'
|
||||
disabled = false
|
||||
|
||||
[jobs]
|
||||
symbol = "✦"
|
||||
format = "( [$symbol$number]($style))"
|
||||
style = "bold blue"
|
||||
symbol = '✦'
|
||||
format = '( [$symbol$number]($style))'
|
||||
style = 'bold blue'
|
||||
symbol_threshold = 1
|
||||
number_threshold = 1
|
||||
disabled = false
|
||||
|
||||
[shell]
|
||||
bash_indicator = " bsh"
|
||||
fish_indicator = " fsh"
|
||||
zsh_indicator = " zsh"
|
||||
powershell_indicator = " psh"
|
||||
bash_indicator = ' bsh'
|
||||
fish_indicator = ' fsh'
|
||||
zsh_indicator = ' zsh'
|
||||
powershell_indicator = ' psh'
|
||||
ion_indicator = " ion"
|
||||
elvish_indicator = " esh"
|
||||
tcsh_indicator = " tsh"
|
||||
xonsh_indicator = " xsh"
|
||||
cmd_indicator = " cmd"
|
||||
nu_indicator = " nu"
|
||||
format = "[$indicator]($style)"
|
||||
elvish_indicator = ' esh'
|
||||
tcsh_indicator = ' tsh'
|
||||
xonsh_indicator = ' xsh'
|
||||
cmd_indicator = ' cmd'
|
||||
nu_indicator = ' nu'
|
||||
format = '[$indicator]($style)'
|
||||
disabled = true
|
||||
|
||||
[localip]
|
||||
format = '( @[$localipv4](bold red))'
|
||||
disabled = true
|
||||
|
||||
[os]
|
||||
format = '( [$symbol]($style))'
|
||||
disabled = true
|
||||
|
||||
[battery]
|
||||
format = "( [$symbol$percentage]($style))"
|
||||
format = '( [$symbol$percentage]($style))'
|
||||
|
||||
[[battery.display]]
|
||||
threshold = 10
|
||||
style = "bold red"
|
||||
style = 'bold red'
|
||||
|
||||
[memory_usage]
|
||||
threshold = 75
|
||||
symbol = " "
|
||||
symbol = ' '
|
||||
format = '( [$symbol${ram}]($style))'
|
||||
disabled = true
|
||||
|
||||
@@ -218,217 +269,326 @@ style = "bold fg:239"
|
||||
disabled = false
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Languages
|
||||
# MARK: Languages
|
||||
# ------------------------------------------------------------------------------
|
||||
#
|
||||
|
||||
[buf]
|
||||
format = "( [$symbol($version)]($style))"
|
||||
symbol = " "
|
||||
symbol = ' '
|
||||
format = '( [$symbol($version)]($style))'
|
||||
disabled = false
|
||||
|
||||
[bun]
|
||||
symbol = ' '
|
||||
format = '( [$symbol$version]($style))'
|
||||
style = 'bold blue'
|
||||
disabled = false
|
||||
|
||||
[c]
|
||||
format = '( [$symbol($version(-$name))]($style))'
|
||||
disabled = true
|
||||
|
||||
[cmake]
|
||||
format = "( [$symbol$version]($style))"
|
||||
disabled = true
|
||||
|
||||
[crystal]
|
||||
format = "( [$symbol$version]($style))"
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = true
|
||||
|
||||
[cobol]
|
||||
symbol = "漣 "
|
||||
format = "( [$symbol$version]($style))"
|
||||
symbol = ' '
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = true
|
||||
|
||||
[crystal]
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = false
|
||||
|
||||
[daml]
|
||||
format = '( [$symbol($version)]($style))'
|
||||
disabled = true
|
||||
|
||||
[dart]
|
||||
symbol = " "
|
||||
format = "( [$symbol$version]($style))"
|
||||
disabled = true
|
||||
symbol = ' '
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = false
|
||||
|
||||
[deno]
|
||||
format = "( [$symbol$version]($style))"
|
||||
disabled = true
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = false
|
||||
|
||||
[dotnet]
|
||||
symbol = " "
|
||||
format = "( [$symbol($version)( 🎯 $tfm)]($style))"
|
||||
disabled = true
|
||||
symbol = ' '
|
||||
format = '( [$symbol($version)( 🎯 $tfm)]($style))'
|
||||
disabled = false
|
||||
|
||||
[elixir]
|
||||
symbol = " "
|
||||
symbol = ' '
|
||||
format = '( [$symbol($version \(OTP $otp_version\))]($style))'
|
||||
disabled = true
|
||||
disabled = false
|
||||
|
||||
[elm]
|
||||
symbol = " "
|
||||
format = "( [$symbol$version]($style))"
|
||||
symbol = ' '
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = true
|
||||
|
||||
[erlang]
|
||||
symbol = " "
|
||||
format = "( [$symbol$version]($style))"
|
||||
symbol = ' '
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = true
|
||||
|
||||
[fennel]
|
||||
format = '( [$symbol($version)]($style))'
|
||||
disabled = true
|
||||
|
||||
[fortran]
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = true
|
||||
|
||||
[gleam]
|
||||
format = '( [$symbol($version)]($style))'
|
||||
disabled = false
|
||||
|
||||
[golang]
|
||||
symbol = " "
|
||||
format = "( [$symbol$version]($style))"
|
||||
symbol = ' '
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = false
|
||||
|
||||
[guix_shell]
|
||||
format = '( [$symbol]($style))'
|
||||
disabled = true
|
||||
|
||||
[haskell]
|
||||
format = '( [$symbol($version)]($style))'
|
||||
disabled = false
|
||||
|
||||
[haxe]
|
||||
format = '( [$symbol($version)]($style))'
|
||||
disabled = true
|
||||
|
||||
[java]
|
||||
symbol = " "
|
||||
format = "( [$symbol$version]($style))"
|
||||
symbol = ' '
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = true
|
||||
|
||||
[julia]
|
||||
symbol = " "
|
||||
format = "( [$symbol$version]($style))"
|
||||
symbol = ' '
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = true
|
||||
|
||||
[kotlin]
|
||||
format = "( [$symbol$version]($style))"
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = true
|
||||
|
||||
[lua]
|
||||
symbol = " "
|
||||
format = "( [$symbol$version]($style))"
|
||||
disabled = true
|
||||
symbol = ' '
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = false
|
||||
|
||||
[nim]
|
||||
symbol = " "
|
||||
format = "( [$symbol$version]($style))"
|
||||
symbol = ' '
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = true
|
||||
|
||||
[nodejs]
|
||||
symbol = " "
|
||||
format = "( [$symbol$version]($style))"
|
||||
disabled = true
|
||||
symbol = ' '
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = false
|
||||
|
||||
[ocaml]
|
||||
format = '( [$symbol$version(\($switch_indicator$switch_name\))]($style))'
|
||||
disabled = true
|
||||
|
||||
[perl]
|
||||
symbol = " "
|
||||
format = "( [$symbol$version]($style))"
|
||||
symbol = ' '
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = true
|
||||
|
||||
[php]
|
||||
symbol = " "
|
||||
format = "( [$symbol$version]($style))"
|
||||
disabled = true
|
||||
symbol = ' '
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = false
|
||||
|
||||
[purescript]
|
||||
format = "( [$symbol$version]($style))"
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = true
|
||||
|
||||
[python]
|
||||
symbol = " "
|
||||
symbol = ' '
|
||||
format = '( [${symbol}${pyenv_prefix}${version}( \($virtualenv\))]($style))'
|
||||
disabled = true
|
||||
|
||||
[raku]
|
||||
format = '( [$symbol($version-$vm_version)]($style))'
|
||||
disabled = true
|
||||
|
||||
[rlang]
|
||||
format = "( [$symbol$version]($style))"
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = true
|
||||
|
||||
[red]
|
||||
format = "( [$symbol$version]($style))"
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = true
|
||||
|
||||
[ruby]
|
||||
symbol = " "
|
||||
format = "( [$symbol$version]($style))"
|
||||
disabled = true
|
||||
symbol = ' '
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = false
|
||||
|
||||
[rust]
|
||||
symbol = " "
|
||||
format = "( [$symbol$version]($style))"
|
||||
disabled = true
|
||||
symbol = ' '
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = false
|
||||
|
||||
[scala]
|
||||
symbol = " "
|
||||
format = "( [$symbol$version]($style))"
|
||||
symbol = ' '
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = true
|
||||
|
||||
[solidity]
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = false
|
||||
|
||||
[swift]
|
||||
symbol = "ﯣ "
|
||||
format = "( [$symbol$version]($style))"
|
||||
disabled = true
|
||||
symbol = ' '
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = false
|
||||
|
||||
[vlang]
|
||||
format = "( [$symbol$version]($style))"
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = true
|
||||
|
||||
[zig]
|
||||
format = "( [$symbol$version]($style))"
|
||||
disabled = true
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = false
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Tools
|
||||
# MARK: Tools
|
||||
# ------------------------------------------------------------------------------
|
||||
#
|
||||
|
||||
[aws]
|
||||
symbol = " "
|
||||
symbol = ' '
|
||||
format = '( [$symbol($profile)( \($region\))( \[$duration\])]($style))'
|
||||
disabled = true
|
||||
|
||||
[azure]
|
||||
symbol = "ﴃ "
|
||||
format = "( [$symbol($subscription)]($style))"
|
||||
symbol = ' '
|
||||
format = '( [$symbol($subscription)]($style))'
|
||||
disabled = true
|
||||
|
||||
[conda]
|
||||
symbol = " "
|
||||
format = "( [$symbol$environment]($style))"
|
||||
symbol = ' '
|
||||
format = '( [$symbol$environment]($style))'
|
||||
|
||||
[container]
|
||||
format = '( [$symbol \[$name\]]($style))'
|
||||
disabled = false
|
||||
|
||||
[direnv]
|
||||
symbol = ' '
|
||||
format = '( [$symbol]($style)[(($loaded/)$allowed)](red))'
|
||||
allowed_msg = ''
|
||||
denied_msg = 'denied'
|
||||
loaded_msg = ''
|
||||
not_allowed_msg = 'not allowed'
|
||||
unloaded_msg = ''
|
||||
disabled = false
|
||||
style = 'bold green'
|
||||
|
||||
[docker_context]
|
||||
symbol = " "
|
||||
format = "( [$symbol$context]($style))"
|
||||
symbol = ' '
|
||||
format = '( [$symbol$context]($style))'
|
||||
disabled = true
|
||||
|
||||
[env_var]
|
||||
format = '( with [$env_value]($style))'
|
||||
disabled = true
|
||||
|
||||
[fossil_branch]
|
||||
format = '( [$symbol$branch]($style))'
|
||||
disabled = true
|
||||
|
||||
[gcloud]
|
||||
symbol = " "
|
||||
symbol = ' '
|
||||
format = '( [$symbol$account(@$domain)(\($region\))]($style))'
|
||||
disabled = true
|
||||
|
||||
[helm]
|
||||
format = "( [$symbol$version]($style))"
|
||||
[gradle]
|
||||
format = '( [$symbol($version)]($style))'
|
||||
disabled = true
|
||||
|
||||
[helm]
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = false
|
||||
|
||||
[kubernetes]
|
||||
symbol = "☸ "
|
||||
symbol = '☸ '
|
||||
format = '( [$symbol$context(\($namespace\))]($style))'
|
||||
disabled = false
|
||||
|
||||
[meson]
|
||||
format = '( [$symbol$project]($style))'
|
||||
disabled = true
|
||||
|
||||
[mise]
|
||||
format = '( [$symbol$health]($style))'
|
||||
disabled = true
|
||||
|
||||
[nats]
|
||||
format = '( [$symbol$name]($style))'
|
||||
disabled = false
|
||||
|
||||
[netns]
|
||||
format = '( [$symbol \[$name\]]($style))'
|
||||
disabled = true
|
||||
|
||||
[nix_shell]
|
||||
symbol = " "
|
||||
symbol = ' '
|
||||
format = '( [$symbol$state(\($name\))]($style))'
|
||||
disabled = false
|
||||
|
||||
[opa]
|
||||
format = '( [$symbol($version)]($style))'
|
||||
disabled = true
|
||||
|
||||
[openstack]
|
||||
symbol = " "
|
||||
symbol = ' '
|
||||
format = '( [$symbol$cloud(\($project\))]($style))'
|
||||
disabled = true
|
||||
|
||||
[package]
|
||||
symbol = " "
|
||||
format = "( [$symbol$version]($style))"
|
||||
symbol = ' '
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = true
|
||||
|
||||
[pijul_channel]
|
||||
format = '( [$symbol$channel]($style))'
|
||||
disabled = true
|
||||
|
||||
[pulumi]
|
||||
format = "( [$symbol$stack]($style))"
|
||||
format = '( [$symbol$stack]($style))'
|
||||
disabled = true
|
||||
|
||||
[quarto]
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = false
|
||||
|
||||
[singularity]
|
||||
format = '( [$symbol\[$env\]]($style))'
|
||||
disabled = true
|
||||
|
||||
[terraform]
|
||||
format = "( [$symbol$workspace]($style))"
|
||||
[spack]
|
||||
format = '( [$symbol$environment]($style))'
|
||||
disabled = true
|
||||
|
||||
[terraform]
|
||||
format = '( [$symbol$workspace]($style))'
|
||||
disabled = false
|
||||
|
||||
[typst]
|
||||
format = '( [$symbol$version]($style))'
|
||||
disabled = false
|
||||
|
||||
[vagrant]
|
||||
format = "( [$symbol($version )]($style))"
|
||||
disabled = true
|
||||
format = '( [$symbol($version)]($style))'
|
||||
disabled = false
|
||||
|
||||
[vcsh]
|
||||
format = "(vcsh [$symbol$repo]($style))"
|
||||
format = '(vcsh [$symbol$repo]($style))'
|
||||
disabled = true
|
||||
|
||||
76
config/tlrc/config.toml
Normal file
76
config/tlrc/config.toml
Normal file
@@ -0,0 +1,76 @@
|
||||
[output]
|
||||
show_title = true
|
||||
platform_title = false
|
||||
show_hyphens = true
|
||||
example_prefix = "- "
|
||||
compact = false
|
||||
raw_markdown = false
|
||||
|
||||
[indent]
|
||||
title = 2
|
||||
description = 2
|
||||
bullet = 2
|
||||
example = 4
|
||||
|
||||
[style.title]
|
||||
color = "magenta"
|
||||
background = "default"
|
||||
bold = true
|
||||
underline = false
|
||||
italic = false
|
||||
dim = false
|
||||
strikethrough = false
|
||||
|
||||
[style.description]
|
||||
color = "default"
|
||||
background = "default"
|
||||
bold = false
|
||||
underline = false
|
||||
italic = false
|
||||
dim = false
|
||||
strikethrough = false
|
||||
|
||||
[style.bullet]
|
||||
color = "default"
|
||||
background = "default"
|
||||
bold = false
|
||||
underline = false
|
||||
italic = false
|
||||
dim = false
|
||||
strikethrough = false
|
||||
|
||||
[style.example]
|
||||
color = "green"
|
||||
background = "default"
|
||||
bold = false
|
||||
underline = false
|
||||
italic = false
|
||||
dim = false
|
||||
strikethrough = false
|
||||
|
||||
[style.url]
|
||||
color = "cyan"
|
||||
background = "default"
|
||||
bold = false
|
||||
underline = true
|
||||
italic = false
|
||||
dim = false
|
||||
strikethrough = false
|
||||
|
||||
[style.inline_code]
|
||||
color = "yellow"
|
||||
background = "default"
|
||||
bold = false
|
||||
underline = false
|
||||
italic = false
|
||||
dim = false
|
||||
strikethrough = false
|
||||
|
||||
[style.placeholder]
|
||||
color = "red"
|
||||
background = "default"
|
||||
bold = false
|
||||
underline = false
|
||||
italic = false
|
||||
dim = false
|
||||
strikethrough = false
|
||||
53
config/xkeysnail/README.md
Normal file
53
config/xkeysnail/README.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# jimeh's xkeysnail setup
|
||||
|
||||
The goal here is to use [xkeysnail][] to make Linux keyboard shortcuts mostly
|
||||
behave the same as on macOS.
|
||||
|
||||
[xkeysnail]: https://github.com/mooz/xkeysnail
|
||||
|
||||
## Pre-requisites
|
||||
|
||||
To be able to run xkeysnail as a non-root user / with sudo, we need to perform
|
||||
some initial setup.
|
||||
|
||||
1. Create a `uinput` group and add your user to it:
|
||||
```bash
|
||||
sudo groupadd -f uinput
|
||||
sudo gpasswd -a $USER uinput
|
||||
```
|
||||
2. Create udev rules for xkeysnail:
|
||||
```bash
|
||||
cat <<EOF | sudo tee /etc/udev/rules.d/70-xkeysnail.rules
|
||||
KERNEL=="uinput", GROUP="uinput", MODE="0660", OPTIONS+="static_node=uinput"
|
||||
KERNEL=="event[0-9]*", GROUP="uinput", MODE="0660"
|
||||
EOF
|
||||
```
|
||||
3. Reboot.
|
||||
|
||||
(Borrowed from [here][1].)
|
||||
|
||||
[1]: https://github.com/mooz/xkeysnail/issues/64#issuecomment-600380800
|
||||
|
||||
## Setup systemd user service
|
||||
|
||||
1. Copy service into place:
|
||||
```bash
|
||||
mkdir -p $HOME/.config/systemd/user
|
||||
cp ./systemd.service $HOME/.config/systemd/user/xkeysnail.service
|
||||
```
|
||||
2. Reload user units:
|
||||
```bash
|
||||
systemctl --user daemon-reload
|
||||
```
|
||||
3. Enable service:
|
||||
```bash
|
||||
systemctl --user enable xkeysnail.service
|
||||
```
|
||||
4. Start service:
|
||||
```bash
|
||||
systemctl --user start xkeysnail.service
|
||||
```
|
||||
5. Check status of service:
|
||||
```bash
|
||||
systemctl --user status xkeysnail.service
|
||||
```
|
||||
132
config/xkeysnail/config.py
Normal file
132
config/xkeysnail/config.py
Normal file
@@ -0,0 +1,132 @@
|
||||
from xkeysnail.transform import *
|
||||
from xkeysnail.key import Key
|
||||
|
||||
define_modmap({
|
||||
# Treat CAPSLOCK as CTRL.
|
||||
Key.CAPSLOCK: Key.LEFT_CTRL,
|
||||
|
||||
# Ensure ` and ~ key is next to left shift.
|
||||
Key.KEY_102ND: Key.GRAVE,
|
||||
Key.GRAVE: Key.KEY_102ND,
|
||||
})
|
||||
|
||||
define_keymap(lambda wm_class: wm_class in ("Gnome-terminal", "Guake"), {
|
||||
}, "Terminal keys")
|
||||
|
||||
define_keymap(lambda wm_class: wm_class in ("firefox", "Google-chrome"), {
|
||||
K("Super-Shift-Left_Brace"): K("C-Shift-tab"),
|
||||
K("Super-Shift-Right_Brace"): K("C-tab"),
|
||||
K("Super-Left_Brace"): K("M-left"),
|
||||
K("Super-Right_Brace"): K("M-right"),
|
||||
K("Super-Shift-t"): K("C-Shift-t"),
|
||||
}, "Browser keys")
|
||||
|
||||
define_keymap(lambda wm_class: wm_class in ("1Password"), {
|
||||
K("Super-comma"): K("C-comma"),
|
||||
}, "1Password specific keys")
|
||||
|
||||
# Emacs-like keybindings in non-Emacs applications
|
||||
define_keymap(lambda wm_class: wm_class not in ("Emacs", "URxvt", "Gnome-terminal", "Guake"), {
|
||||
K("Super-x"): K("C-x"),
|
||||
K("Super-c"): K("C-c"),
|
||||
K("Super-v"): K("C-v"),
|
||||
|
||||
K("Super-a"): K("C-a"),
|
||||
K("Super-l"): K("C-l"),
|
||||
K("Super-t"): K("C-t"),
|
||||
K("Super-r"): K("C-r"),
|
||||
K("Super-z"): K("C-z"),
|
||||
K("Super-Shift-z"): K("C-Shift-z"),
|
||||
|
||||
# Cursor
|
||||
K("C-b"): with_mark(K("left")),
|
||||
K("C-f"): with_mark(K("right")),
|
||||
K("C-p"): with_mark(K("up")),
|
||||
K("C-n"): with_mark(K("down")),
|
||||
K("C-h"): with_mark(K("backspace")),
|
||||
K("Super-f"): K("C-f"),
|
||||
K("Super-n"): K("C-n"),
|
||||
K("Super-p"): K("C-p"),
|
||||
K("Super-h"): K("C-h"),
|
||||
|
||||
# Forward/Backward word
|
||||
K("M-b"): with_mark(K("C-left")),
|
||||
K("M-f"): with_mark(K("C-right")),
|
||||
|
||||
# Beginning/End of line
|
||||
K("C-a"): with_mark(K("home")),
|
||||
K("C-e"): with_mark(K("end")),
|
||||
|
||||
# Page up/down
|
||||
K("M-v"): with_mark(K("page_up")),
|
||||
K("C-v"): with_mark(K("page_down")),
|
||||
|
||||
# Beginning/End of file
|
||||
K("M-Shift-comma"): with_mark(K("C-home")),
|
||||
K("M-Shift-dot"): with_mark(K("C-end")),
|
||||
|
||||
# Newline
|
||||
K("C-m"): K("enter"),
|
||||
K("C-j"): K("enter"),
|
||||
K("C-o"): [K("enter"), K("left")],
|
||||
K("Super-o"): K("C-o"),
|
||||
|
||||
# Copy
|
||||
K("C-w"): [K("C-x"), set_mark(False)],
|
||||
K("M-w"): [K("C-c"), set_mark(False)],
|
||||
K("C-y"): [K("C-v"), set_mark(False)],
|
||||
K("Super-w"): K("C-w"),
|
||||
|
||||
# Delete
|
||||
K("C-d"): [K("delete"), set_mark(False)],
|
||||
K("M-d"): [K("C-delete"), set_mark(False)],
|
||||
K("Super-d"): K("C-d"),
|
||||
|
||||
# Backspace
|
||||
K("M-backspace"): [K("C-backspace"), set_mark(False)],
|
||||
|
||||
# Kill line
|
||||
# K("C-k"): [K("Shift-end"), K("C-x"), set_mark(False)],
|
||||
|
||||
# Undo
|
||||
K("M-minus"): [K("C-z"), set_mark(False)],
|
||||
# K("C-slash"): [K("C-z"), set_mark(False)],
|
||||
# K("C-Shift-ro"): K("C-z"),
|
||||
|
||||
# Mark
|
||||
K("C-space"): set_mark(True),
|
||||
K("C-M-space"): with_or_set_mark(K("C-right")),
|
||||
|
||||
# Search
|
||||
# K("C-s"): K("F3"),
|
||||
# K("C-r"): K("Shift-F3"),
|
||||
# K("M-Shift-key_5"): K("C-h"),
|
||||
K("Super-s"): K("C-s"),
|
||||
|
||||
# Cancel
|
||||
K("C-g"): [K("esc"), set_mark(False)],
|
||||
K("Super-g"): K("C-g"),
|
||||
K("Super-Shift-g"): K("C-Shift-g"),
|
||||
|
||||
# Escape
|
||||
K("C-q"): escape_next_key,
|
||||
K("C-left_brace"): K("esc"),
|
||||
|
||||
# C-x YYY
|
||||
K("C-x"): {
|
||||
# C-x h (select all)
|
||||
K("h"): [K("C-home"), K("C-a"), set_mark(True)],
|
||||
# C-x C-f (open)
|
||||
K("C-f"): K("C-o"),
|
||||
# C-x C-s (save)
|
||||
K("C-s"): K("C-s"),
|
||||
# C-x k (kill tab)
|
||||
# K("k"): K("C-f4"),
|
||||
# C-x C-c (exit)
|
||||
# K("C-c"): K("C-q"),
|
||||
# cancel
|
||||
K("C-g"): pass_through_key,
|
||||
# C-x u (undo)
|
||||
# K("u"): [K("C-z"), set_mark(False)],
|
||||
}
|
||||
}, "Emacs-like keys")
|
||||
13
config/xkeysnail/systemd.service
Normal file
13
config/xkeysnail/systemd.service
Normal file
@@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=xkeysnail
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
KillMode=process
|
||||
ExecStart=%h/.local/share/mise/shims/xkeysnail --watch --quiet %h/.config/xkeysnail/config.py
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
Environment=DISPLAY=:0
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
1
cursor/.gitignore
vendored
Normal file
1
cursor/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
./cache/
|
||||
75
cursor/extensions.cursor.lock
Normal file
75
cursor/extensions.cursor.lock
Normal file
@@ -0,0 +1,75 @@
|
||||
# cursor Extensions
|
||||
# Generated on Sat Mar 8 23:55:51 GMT 2025
|
||||
|
||||
alefragnani.project-manager@12.8.0
|
||||
antiantisepticeye.vscode-color-picker@0.0.4
|
||||
antyos.openscad@1.3.2
|
||||
arturodent.command-alias@0.6.2
|
||||
bibhasdn.unique-lines@1.0.0
|
||||
bodil.file-browser@0.2.11
|
||||
britesnow.vscode-toggle-quotes@0.3.6
|
||||
bufbuild.vscode-buf@0.7.0
|
||||
carlos-algms.make-task-provider@2.5.1
|
||||
christian-kohler.path-intellisense@2.10.0
|
||||
connor4312.esbuild-problem-matchers@0.0.3
|
||||
connorshea.vscode-ruby-test-adapter@0.9.2
|
||||
ctf0.macros@1.1.1
|
||||
dbaeumer.vscode-eslint@3.0.10
|
||||
dnut.rewrap-revived@1.16.3
|
||||
emeraldwalk.runonsave@0.2.7
|
||||
exiasr.hadolint@1.1.2
|
||||
foxundermoon.shell-format@7.2.5
|
||||
github.remotehub@0.64.0
|
||||
github.vscode-github-actions@0.27.1
|
||||
github.vscode-pull-request-github@0.102.0
|
||||
gofenix.go-lines@0.0.10
|
||||
golang.go@0.46.1
|
||||
gruntfuggly.todo-tree@0.0.226
|
||||
hashicorp.terraform@2.34.3
|
||||
hbenl.vscode-test-explorer@2.22.1
|
||||
humao.rest-client@0.25.1
|
||||
hverlin.mise-vscode@0.47.8
|
||||
joshbolduc.commitlint@2.6.2
|
||||
kahole.magit@0.6.66
|
||||
karunamurti.haml@1.4.1
|
||||
koichisasada.vscode-rdbg@0.2.2
|
||||
letrieu.expand-region@0.1.4
|
||||
m4ns0ur.base64@1.0.0
|
||||
mattn.lisp@0.1.12
|
||||
mhutchie.git-graph@1.30.0
|
||||
ms-azuretools.vscode-docker@1.29.4
|
||||
ms-python.debugpy@2024.6.0
|
||||
ms-python.python@2024.12.3
|
||||
ms-python.vscode-pylance@2024.8.1
|
||||
ms-vscode-remote.remote-containers@0.394.0
|
||||
ms-vscode-remote.remote-ssh@0.113.1
|
||||
ms-vscode-remote.remote-ssh-edit@0.87.0
|
||||
ms-vscode.extension-test-runner@0.0.12
|
||||
ms-vscode.hexeditor@1.11.1
|
||||
ms-vscode.remote-explorer@0.4.3
|
||||
ms-vscode.remote-repositories@0.42.0
|
||||
ms-vscode.remote-server@1.5.2
|
||||
ms-vscode.test-adapter-converter@0.2.1
|
||||
ms-vscode.vscode-speech@0.12.1
|
||||
ms-vsliveshare.vsliveshare@1.0.5948
|
||||
pflannery.vscode-versionlens@1.16.2
|
||||
pkief.material-icon-theme@5.20.0
|
||||
redhat.vscode-xml@0.28.0
|
||||
redhat.vscode-yaml@1.17.0
|
||||
rrudi.vscode-dired@0.0.9
|
||||
rust-lang.rust-analyzer@0.3.2330
|
||||
shopify.ruby-extensions-pack@0.1.13
|
||||
shopify.ruby-lsp@0.9.7
|
||||
sidneys1.gitconfig@2.0.1
|
||||
sorbet.sorbet-vscode-extension@0.3.40
|
||||
stuart.unique-window-colors@1.0.51
|
||||
sumneko.lua@3.13.6
|
||||
swellaby.vscode-rust-test-adapter@0.11.0
|
||||
tamasfe.even-better-toml@0.21.2
|
||||
tuttieee.emacs-mcx@0.65.1
|
||||
tyriar.sort-lines@1.12.0
|
||||
viktorzetterstrom.non-breaking-space-highlighter@0.0.3
|
||||
wenhoujx.swiper@2.1.2
|
||||
zhuangtongfa.material-theme@3.19.0
|
||||
ziyasal.vscode-open-in-github@1.3.6
|
||||
zxh404.vscode-proto3@0.5.5
|
||||
77
cursor/extensions.vscode-insiders.lock
Normal file
77
cursor/extensions.vscode-insiders.lock
Normal file
@@ -0,0 +1,77 @@
|
||||
# vscode-insiders Extensions
|
||||
# Generated on Sun Mar 9 00:18:12 GMT 2025
|
||||
|
||||
alefragnani.project-manager@12.8.0
|
||||
antiantisepticeye.vscode-color-picker@0.0.4
|
||||
antyos.openscad@1.3.2
|
||||
arturodent.command-alias@0.6.2
|
||||
bibhasdn.unique-lines@1.0.0
|
||||
bodil.file-browser@0.2.11
|
||||
britesnow.vscode-toggle-quotes@0.3.6
|
||||
bufbuild.vscode-buf@0.7.0
|
||||
carlos-algms.make-task-provider@2.5.1
|
||||
christian-kohler.path-intellisense@2.10.0
|
||||
connor4312.esbuild-problem-matchers@0.0.3
|
||||
connorshea.vscode-ruby-test-adapter@0.9.2
|
||||
ctf0.macros@1.1.1
|
||||
dbaeumer.vscode-eslint@3.0.10
|
||||
dnut.rewrap-revived@1.16.3
|
||||
emeraldwalk.runonsave@0.2.7
|
||||
exiasr.hadolint@1.1.2
|
||||
foxundermoon.shell-format@7.2.5
|
||||
github.copilot@1.280.1420
|
||||
github.copilot-chat@0.25.2025022401
|
||||
github.remotehub@0.64.0
|
||||
github.vscode-github-actions@0.27.1
|
||||
github.vscode-pull-request-github@0.106.0
|
||||
gofenix.go-lines@0.0.10
|
||||
golang.go@0.46.1
|
||||
gruntfuggly.todo-tree@0.0.226
|
||||
hashicorp.terraform@2.34.3
|
||||
hbenl.vscode-test-explorer@2.22.1
|
||||
humao.rest-client@0.25.1
|
||||
hverlin.mise-vscode@0.47.8
|
||||
joshbolduc.commitlint@2.6.2
|
||||
kahole.magit@0.6.66
|
||||
karunamurti.haml@1.4.1
|
||||
koichisasada.vscode-rdbg@0.2.2
|
||||
letrieu.expand-region@0.1.4
|
||||
m4ns0ur.base64@1.0.0
|
||||
mattn.lisp@0.1.12
|
||||
mhutchie.git-graph@1.30.0
|
||||
ms-azuretools.vscode-docker@1.29.4
|
||||
ms-python.debugpy@2025.4.0
|
||||
ms-python.python@2025.2.0
|
||||
ms-python.vscode-pylance@2025.3.1
|
||||
ms-vscode-remote.remote-containers@0.403.0
|
||||
ms-vscode-remote.remote-ssh@0.118.0
|
||||
ms-vscode-remote.remote-ssh-edit@0.87.0
|
||||
ms-vscode.extension-test-runner@0.0.12
|
||||
ms-vscode.hexeditor@1.11.1
|
||||
ms-vscode.remote-explorer@0.4.3
|
||||
ms-vscode.remote-repositories@0.42.0
|
||||
ms-vscode.remote-server@1.5.2
|
||||
ms-vscode.test-adapter-converter@0.2.1
|
||||
ms-vscode.vscode-speech@0.12.1
|
||||
ms-vsliveshare.vsliveshare@1.0.5948
|
||||
pflannery.vscode-versionlens@1.16.2
|
||||
pkief.material-icon-theme@5.20.0
|
||||
redhat.vscode-xml@0.28.0
|
||||
redhat.vscode-yaml@1.17.0
|
||||
rrudi.vscode-dired@0.0.9
|
||||
rust-lang.rust-analyzer@0.3.2330
|
||||
shopify.ruby-extensions-pack@0.1.13
|
||||
shopify.ruby-lsp@0.9.7
|
||||
sidneys1.gitconfig@2.0.1
|
||||
sorbet.sorbet-vscode-extension@0.3.40
|
||||
stuart.unique-window-colors@1.0.51
|
||||
sumneko.lua@3.13.6
|
||||
swellaby.vscode-rust-test-adapter@0.11.0
|
||||
tamasfe.even-better-toml@0.21.2
|
||||
tuttieee.emacs-mcx@0.65.1
|
||||
tyriar.sort-lines@1.12.0
|
||||
viktorzetterstrom.non-breaking-space-highlighter@0.0.3
|
||||
wenhoujx.swiper@2.1.2
|
||||
zhuangtongfa.material-theme@3.19.0
|
||||
ziyasal.vscode-open-in-github@1.3.6
|
||||
zxh404.vscode-proto3@0.5.5
|
||||
75
cursor/extensions.windsurf.lock
Normal file
75
cursor/extensions.windsurf.lock
Normal file
@@ -0,0 +1,75 @@
|
||||
# windsurf Extensions
|
||||
# Generated on Sat Mar 8 23:40:17 GMT 2025
|
||||
|
||||
alefragnani.project-manager@12.8.0
|
||||
antiantisepticeye.vscode-color-picker@0.0.4
|
||||
antyos.openscad@1.3.2
|
||||
arturodent.command-alias@0.6.2
|
||||
bibhasdn.unique-lines@1.0.0
|
||||
bodil.file-browser@0.2.11
|
||||
britesnow.vscode-toggle-quotes@0.3.6
|
||||
bufbuild.vscode-buf@0.7.0
|
||||
carlos-algms.make-task-provider@2.4.2
|
||||
christian-kohler.path-intellisense@2.8.0
|
||||
codeium.windsurfpyright@1.28.0
|
||||
connor4312.esbuild-problem-matchers@0.0.3
|
||||
connorshea.vscode-ruby-test-adapter@0.9.0
|
||||
ctf0.macros@1.1.1
|
||||
dbaeumer.vscode-eslint@3.0.10
|
||||
dnut.rewrap-revived@1.16.3
|
||||
emeraldwalk.runonsave@0.1.0
|
||||
exiasr.hadolint@1.1.2
|
||||
foxundermoon.shell-format@7.0.1
|
||||
github.remotehub@0.64.0
|
||||
github.vscode-github-actions@0.27.1
|
||||
github.vscode-pull-request-github@0.98.0
|
||||
gofenix.go-lines@0.0.10
|
||||
golang.go@0.46.1
|
||||
gruntfuggly.todo-tree@0.0.215
|
||||
hashicorp.terraform@2.34.3
|
||||
hbenl.vscode-test-explorer@2.22.1
|
||||
humao.rest-client@0.26.0
|
||||
hverlin.mise-vscode@0.47.8
|
||||
joshbolduc.commitlint@2.6.2
|
||||
kahole.magit@0.6.66
|
||||
karunamurti.haml@1.4.1
|
||||
koichisasada.vscode-rdbg@0.2.1
|
||||
letrieu.expand-region@0.1.4
|
||||
m4ns0ur.base64@1.0.0
|
||||
mattn.lisp@0.1.12
|
||||
mhutchie.git-graph@1.30.0
|
||||
ms-azuretools.vscode-docker@1.29.4
|
||||
ms-python.debugpy@2025.4.0
|
||||
ms-python.python@2025.2.0
|
||||
ms-vscode-remote.remote-containers@0.394.0
|
||||
ms-vscode-remote.remote-ssh@0.113.1
|
||||
ms-vscode-remote.remote-ssh-edit@0.87.0
|
||||
ms-vscode.extension-test-runner@0.0.12
|
||||
ms-vscode.hexeditor@1.11.1
|
||||
ms-vscode.remote-explorer@0.4.3
|
||||
ms-vscode.remote-repositories@0.42.0
|
||||
ms-vscode.remote-server@1.5.2
|
||||
ms-vscode.test-adapter-converter@0.2.1
|
||||
ms-vscode.vscode-speech@0.12.1
|
||||
ms-vsliveshare.vsliveshare@1.0.5948
|
||||
pflannery.vscode-versionlens@1.16.1
|
||||
pkief.material-icon-theme@5.20.0
|
||||
redhat.vscode-xml@0.28.0
|
||||
redhat.vscode-yaml@1.17.0
|
||||
rrudi.vscode-dired@0.0.9
|
||||
rust-lang.rust-analyzer@0.3.2330
|
||||
shopify.ruby-extensions-pack@0.1.13
|
||||
shopify.ruby-lsp@0.9.7
|
||||
sidneys1.gitconfig@2.0.1
|
||||
sorbet.sorbet-vscode-extension@0.3.40
|
||||
stuart.unique-window-colors@1.0.51
|
||||
sumneko.lua@3.13.6
|
||||
swellaby.vscode-rust-test-adapter@0.11.1
|
||||
tamasfe.even-better-toml@0.21.2
|
||||
tuttieee.emacs-mcx@0.65.1
|
||||
tyriar.sort-lines@1.9.1
|
||||
viktorzetterstrom.non-breaking-space-highlighter@0.0.3
|
||||
wenhoujx.swiper@2.1.2
|
||||
zhuangtongfa.material-theme@3.19.0
|
||||
ziyasal.vscode-open-in-github@1.4.1
|
||||
zxh404.vscode-proto3@0.5.5
|
||||
838
cursor/keybindings.json
Normal file
838
cursor/keybindings.json
Normal file
@@ -0,0 +1,838 @@
|
||||
[
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Command Palette
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Show commands.
|
||||
"key": "ctrl+x m",
|
||||
"command": "workbench.action.showCommands"
|
||||
},
|
||||
{ // Show commands.
|
||||
"key": "ctrl+x ctrl+m",
|
||||
"command": "workbench.action.showCommands"
|
||||
},
|
||||
{ // Show commands.
|
||||
"key": "ctrl+x enter",
|
||||
"command": "workbench.action.showCommands"
|
||||
},
|
||||
{ // Show commands.
|
||||
"key": "alt+x",
|
||||
"command": "workbench.action.showCommands"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Window
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Reset zoom.
|
||||
"key": "cmd+0",
|
||||
"command": "workbench.action.zoomReset"
|
||||
},
|
||||
{ // Toggle sidebar visibility.
|
||||
"key": "ctrl+s",
|
||||
"command": "workbench.action.toggleSidebarVisibility"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Window Tabs
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Go to next window tab.
|
||||
"key": "ctrl+z ctrl+n",
|
||||
"command": "workbench.action.showNextWindowTab"
|
||||
},
|
||||
{ // Go to next window tab.
|
||||
//
|
||||
// This is a workaround for ctrl+n not working globally as down arrow in
|
||||
// all input fields. This relies on Karabiner-Elements to remap ctrl+n to
|
||||
// down arrow.
|
||||
"key": "ctrl+z down",
|
||||
"command": "workbench.action.showNextWindowTab"
|
||||
},
|
||||
{ // Go to next window tab.
|
||||
"key": "shift+cmd+]",
|
||||
"command": "workbench.action.showNextWindowTab"
|
||||
},
|
||||
{ // Go to previous window tab.
|
||||
"key": "ctrl+z ctrl+p",
|
||||
"command": "workbench.action.showPreviousWindowTab"
|
||||
},
|
||||
{ // Go to previous window tab.
|
||||
//
|
||||
// This is a workaround for ctrl+p not working globally as up arrow in
|
||||
// all input fields. This relies on Karabiner-Elements to remap ctrl+p to
|
||||
// up arrow.
|
||||
"key": "ctrl+z up",
|
||||
"command": "workbench.action.showPreviousWindowTab"
|
||||
},
|
||||
{ // Go to previous window tab.
|
||||
"key": "shift+cmd+[",
|
||||
"command": "workbench.action.showPreviousWindowTab"
|
||||
},
|
||||
{ // Create new window tab.
|
||||
"key": "ctrl+z ctrl+c",
|
||||
"command": "workbench.action.newWindowTab"
|
||||
},
|
||||
{ // Merge all window tabs.
|
||||
"key": "ctrl+z ctrl+j",
|
||||
"command": "workbench.action.mergeAllWindowTabs"
|
||||
},
|
||||
{ // Move window tab to new window.
|
||||
"key": "ctrl+z ctrl+t",
|
||||
"command": "workbench.action.moveWindowTabToNewWindow"
|
||||
},
|
||||
{ // Toggle window tabs bar.
|
||||
"key": "ctrl+z ctrl+z",
|
||||
"command": "workbench.action.toggleWindowTabsBar"
|
||||
},
|
||||
{
|
||||
"key": "ctrl+z ctrl+k",
|
||||
"command": "workbench.action.closeWindow"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Save
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Save file.
|
||||
"key": "ctrl+x ctrl+s",
|
||||
"command": "workbench.action.files.save"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: File open
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Open file via file browser extension.
|
||||
"key": "ctrl+x ctrl+f",
|
||||
"command": "file-browser.open",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
{ // Open file via file browser extension.
|
||||
//
|
||||
// This is a workaround for ctrl+f not working globally as right arrow in
|
||||
// all input fields. This relies on Karabiner-Elements to remap ctrl+f to
|
||||
// right arrow.
|
||||
"key": "ctrl+x right",
|
||||
"command": "file-browser.open",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
{ // Open quick open.
|
||||
"key": "ctrl+x ctrl+;",
|
||||
"command": "workbench.action.quickOpen"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: File rename
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Rename file via file browser extension.
|
||||
"key": "ctrl+c r",
|
||||
"command": "file-browser.rename"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Switch and close editor
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Show all editors by most recently used.
|
||||
"key": "ctrl+x ctrl+b",
|
||||
"command": "workbench.action.showAllEditorsByMostRecentlyUsed",
|
||||
"when": "!terminalFocus"
|
||||
},
|
||||
{ // Show all editors by most recently used.
|
||||
//
|
||||
// This is a workaround for ctrl+b not working globally as left arrow in
|
||||
// all input fields. This relies on Karabiner-Elements to remap ctrl+b to
|
||||
// left arrow.
|
||||
"key": "ctrl+x left",
|
||||
"command": "workbench.action.showAllEditorsByMostRecentlyUsed",
|
||||
"when": "!terminalFocus"
|
||||
},
|
||||
{ // Close active editor.
|
||||
"key": "ctrl+x ctrl+k",
|
||||
"command": "workbench.action.closeActiveEditor",
|
||||
"when": "!terminalFocus"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Fullscreen
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Toggle fullscreen.
|
||||
"key": "ctrl+cmd+enter",
|
||||
"command": "workbench.action.toggleFullScreen",
|
||||
"when": "!isIOS"
|
||||
},
|
||||
{ // Toggle fullscreen.
|
||||
"key": "cmd+enter",
|
||||
"command": "workbench.action.toggleFullScreen",
|
||||
"when": "!isIOS"
|
||||
},
|
||||
{ // Disable default toggle fullscreen keybinding.
|
||||
"key": "ctrl+cmd+f",
|
||||
"command": "-workbench.action.toggleFullScreen",
|
||||
"when": "!isIOS"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Editor Navigation
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Go to next editor.
|
||||
"key": "cmd+]",
|
||||
"command": "workbench.action.nextEditor",
|
||||
"when": "!(terminalFocus && terminalHasBeenCreated && !terminalEditorFocus || terminalFocus && terminalProcessSupported && !terminalEditorFocus)"
|
||||
},
|
||||
{ // Go to previous editor.
|
||||
"key": "cmd+[",
|
||||
"command": "workbench.action.previousEditor",
|
||||
"when": "!(terminalFocus && terminalHasBeenCreated && !terminalEditorFocus || terminalFocus && terminalProcessSupported && !terminalEditorFocus)"
|
||||
},
|
||||
{ // Focus next terminal.
|
||||
"key": "cmd+]",
|
||||
"command": "workbench.action.terminal.focusNext",
|
||||
"when": "terminalFocus && terminalHasBeenCreated && !terminalEditorFocus || terminalFocus && terminalProcessSupported && !terminalEditorFocus"
|
||||
},
|
||||
{ // Focus previous terminal.
|
||||
"key": "cmd+[",
|
||||
"command": "workbench.action.terminal.focusPrevious",
|
||||
"when": "terminalFocus && terminalHasBeenCreated && !terminalEditorFocus || terminalFocus && terminalProcessSupported && !terminalEditorFocus"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Editor Group Navigation
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Focus next editor group.
|
||||
"key": "ctrl+x ctrl+o",
|
||||
"command": "workbench.action.focusNextGroup",
|
||||
"when": "!terminalFocus"
|
||||
},
|
||||
{ // Focus previous editor group.
|
||||
"key": "ctrl+x ctrl+i",
|
||||
"command": "workbench.action.focusPreviousGroup",
|
||||
"when": "!terminalFocus"
|
||||
},
|
||||
{ // Navigate up.
|
||||
"key": "alt+i",
|
||||
"command": "workbench.action.navigateUp",
|
||||
"when": "!terminalFocus"
|
||||
},
|
||||
{ // Navigate up.
|
||||
//
|
||||
// Workaround for alt+i not working in VSCode. Relies on Karabiner-Elements
|
||||
// to remap alt+i to cmd+alt+up.
|
||||
"key": "cmd+alt+up",
|
||||
"command": "workbench.action.navigateUp",
|
||||
"when": "!terminalFocus"
|
||||
},
|
||||
{ // Navigate right.
|
||||
"key": "alt+l",
|
||||
"command": "workbench.action.navigateRight",
|
||||
},
|
||||
{ // Navigate left.
|
||||
"key": "alt+j",
|
||||
"command": "workbench.action.navigateLeft",
|
||||
},
|
||||
{ // Navigate down.
|
||||
"key": "alt+k",
|
||||
"command": "workbench.action.navigateDown",
|
||||
},
|
||||
{ // Navigate up back to editor from terminal.
|
||||
"key": "alt+i",
|
||||
"command": "workbench.action.focusActiveEditorGroup",
|
||||
"when": "terminalFocus"
|
||||
},
|
||||
{ // Navigate up back to editor from terminal.
|
||||
//
|
||||
// Workaround for alt+i not working in VSCode. Relies on Karabiner-Elements
|
||||
// to remap alt+i to cmd+alt+up.
|
||||
"key": "cmd+alt+up",
|
||||
"command": "workbench.action.focusActiveEditorGroup",
|
||||
"when": "terminalFocus"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Editor group layout
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Even editor widths.
|
||||
"key": "ctrl+x space",
|
||||
"command": "workbench.action.evenEditorWidths",
|
||||
"when": "!terminalFocus"
|
||||
},
|
||||
{
|
||||
"key": "ctrl+z ctrl+enter",
|
||||
"command": "workbench.action.toggleMaximizeEditorGroup",
|
||||
"when": "editorPartMaximizedEditorGroup || editorPartMultipleEditorGroups"
|
||||
},
|
||||
{
|
||||
"key": "ctrl+z enter",
|
||||
"command": "workbench.action.minimizeOtherEditors",
|
||||
"when": "editorPartMaximizedEditorGroup || editorPartMultipleEditorGroups"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Move active editor group
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Move active editor group up.
|
||||
"key": "ctrl+shift+i",
|
||||
"command": "workbench.action.moveActiveEditorGroupUp"
|
||||
},
|
||||
{ // Move active editor group down.
|
||||
"key": "ctrl+shift+k",
|
||||
"command": "workbench.action.moveActiveEditorGroupDown"
|
||||
},
|
||||
{ // Move active editor group left.
|
||||
"key": "ctrl+shift+j",
|
||||
"command": "workbench.action.moveActiveEditorGroupLeft"
|
||||
},
|
||||
{ // Move active editor group right.
|
||||
"key": "ctrl+shift+l",
|
||||
"command": "workbench.action.moveActiveEditorGroupRight"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Move active editor into group
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Move active editor into group above.
|
||||
"key": "alt+shift+i",
|
||||
"command": "workbench.action.moveEditorToAboveGroup"
|
||||
},
|
||||
{ // Move active editor into group above.
|
||||
//
|
||||
// Workaround for alt+i not working in VSCode. Relies on Karabiner-Elements
|
||||
// to remap alt+i to cmd+alt+up.
|
||||
"key": "cmd+alt+shift+up",
|
||||
"command": "workbench.action.moveEditorToAboveGroup"
|
||||
},
|
||||
{ // Move active editor into group below.
|
||||
"key": "alt+shift+k",
|
||||
"command": "workbench.action.moveEditorToBelowGroup"
|
||||
},
|
||||
{ // Move active editor into group left.
|
||||
"key": "alt+shift+j",
|
||||
"command": "workbench.action.moveEditorToLeftGroup"
|
||||
},
|
||||
{ // Move active editor into group right.
|
||||
"key": "alt+shift+l",
|
||||
"command": "workbench.action.moveEditorToRightGroup"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Undo/redo
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Undo.
|
||||
"key": "alt+-",
|
||||
"command": "undo"
|
||||
},
|
||||
{ // Redo.
|
||||
"key": "alt+shift+-",
|
||||
"command": "redo"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Scrolling
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Scroll half page down.
|
||||
"key": "ctrl+v",
|
||||
"command": "editorScroll",
|
||||
"args": {
|
||||
"to": "down",
|
||||
"by": "halfPage",
|
||||
"revealCursor": true,
|
||||
"value": 1
|
||||
},
|
||||
"when": "editorTextFocus && !suggestWidgetVisible"
|
||||
},
|
||||
{ // Scroll half page up.
|
||||
"key": "alt+v",
|
||||
"command": "editorScroll",
|
||||
"args": {
|
||||
"to": "up",
|
||||
"by": "halfPage",
|
||||
"revealCursor": true,
|
||||
"value": 1
|
||||
},
|
||||
"when": "editorTextFocus && !suggestWidgetVisible"
|
||||
},
|
||||
{ // Disable awesome-emacs-keymap scroll down keybinding.
|
||||
"key": "ctrl+v",
|
||||
"command": "-emacs-mcx.scrollUpCommand",
|
||||
"when": "editorTextFocus && !suggestWidgetVisible"
|
||||
},
|
||||
{ // Disable awesome-emacs-keymap scroll up keybinding.
|
||||
"key": "alt+v",
|
||||
"command": "-emacs-mcx.scrollDownCommand",
|
||||
"when": "editorTextFocus && !config.emacs-mcx.useMetaPrefixMacCmd && !suggestWidgetVisible"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Suggestions
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Trigger suggestions.
|
||||
"key": "ctrl+/",
|
||||
"command": "editor.action.triggerSuggest",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
{ // Toggle suggestion details.
|
||||
"key": "ctrl+/",
|
||||
"command": "toggleSuggestionDetails",
|
||||
"when": "editorTextFocus && suggestWidgetVisible"
|
||||
},
|
||||
{ // Accept next word.
|
||||
"key": "shift+alt+f",
|
||||
"command": "editor.action.inlineSuggest.acceptNextWord"
|
||||
},
|
||||
{ // Accept next word.
|
||||
//
|
||||
// This is a workaround for alt+f not working globally to move to next word
|
||||
// in all input fields. This relies on Karabiner-Elements to remap alt+f to
|
||||
// alt+right arrow.
|
||||
"key": "shift+alt+right",
|
||||
"command": "editor.action.inlineSuggest.acceptNextWord"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Text navigation
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Forward paragraph.
|
||||
"key": "alt+e",
|
||||
"command": "emacs-mcx.forwardParagraph",
|
||||
"when": "editorTextFocus && !suggestWidgetVisible"
|
||||
},
|
||||
{ // Forward paragraph.
|
||||
//
|
||||
// This is a workaround for alt+e not working in VSCode. Relies on
|
||||
// Karabiner-Elements to remap alt+e to cmd+alt+right.
|
||||
"key": "cmd+alt+right",
|
||||
"command": "emacs-mcx.forwardParagraph",
|
||||
"when": "editorTextFocus && !suggestWidgetVisible"
|
||||
},
|
||||
{ // Backward paragraph.
|
||||
"key": "alt+a",
|
||||
"command": "emacs-mcx.backwardParagraph",
|
||||
"when": "editorTextFocus && !suggestWidgetVisible"
|
||||
},
|
||||
{ // Go to symbol definition.
|
||||
"key": "ctrl+t",
|
||||
"command": "workbench.action.gotoSymbol",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
{ // Jump to definition.
|
||||
"key": "ctrl+c ctrl+j",
|
||||
"command": "editor.action.revealDefinition"
|
||||
},
|
||||
{ // Navigate back.
|
||||
"key": "alt+g b",
|
||||
"command": "workbench.action.navigateBack"
|
||||
},
|
||||
{ // Navigate back.
|
||||
"key": "alt+g alt+b",
|
||||
"command": "workbench.action.navigateBack"
|
||||
},
|
||||
{ // Peek symbol references.
|
||||
"key": "alt+shift+/",
|
||||
"command": "editor.action.referenceSearch.trigger",
|
||||
"when": "editorHasReferenceProvider && editorTextFocus && !inReferenceSearchEditor && !isInEmbeddedEditor"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Text manipulation
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Set indentation to correct level.
|
||||
//
|
||||
// This was borrowed from the awesome-emacs-keymap extension and modifed to
|
||||
// add the `!cpp.shouldAcceptTab` condition for the sake of Cursor.
|
||||
//
|
||||
// Extension: https://marketplace.visualstudio.com/items?itemName=tuttieee.emacs-mcx
|
||||
"key": "tab",
|
||||
"command": "emacs-mcx.tabToTabStop",
|
||||
"when": "editorTextFocus && !editorReadonly && !inlineSuggestionVisible && !editorHoverFocused && !editorTabMovesFocus && !suggestWidgetVisible && !inSnippetMode && !editorTabCompletion && !editorParameterHintsVisible && !cursorAtInlineEdit && !cpp.shouldAcceptTab"
|
||||
},
|
||||
{ // Cycle spacing.
|
||||
//
|
||||
// This is a basic emulation Emacs' built-in cycle-spacing command. It
|
||||
// doesn't actually cycle spacing, but it performs the first step which is
|
||||
// to replace all spacing surrounding the cursor with a single space.
|
||||
"key": "alt+space",
|
||||
"command": "macros.cycleSpacing",
|
||||
"when": "editorTextFocus && !editorReadonly"
|
||||
},
|
||||
{ // Toggle quotes.
|
||||
//
|
||||
// Extension: https://marketplace.visualstudio.com/items?itemName=BriteSnow.vscode-toggle-quotes
|
||||
"key": "ctrl+'",
|
||||
"command": "editor.togglequotes",
|
||||
"when": "editorTextFocus && !editorReadonly"
|
||||
},
|
||||
{ // Comment line.
|
||||
"key": "ctrl+c /",
|
||||
"command": "editor.action.commentLine",
|
||||
"when": "editorTextFocus && !editorReadonly"
|
||||
},
|
||||
{ // Comment line.
|
||||
"key": "ctrl+c ctrl+/",
|
||||
"command": "editor.action.commentLine",
|
||||
"when": "editorTextFocus && !editorReadonly"
|
||||
},
|
||||
{ // Format document.
|
||||
"key": "ctrl+c ctrl+f",
|
||||
"command": "editor.action.formatDocument",
|
||||
"when": "editorTextFocus && !editorReadonly"
|
||||
},
|
||||
{ // Format document.
|
||||
//
|
||||
// This is a workaround for ctrl+f not working globally as right arrow in
|
||||
// all input fields. This relies on Karabiner-Elements to remap ctrl+f to
|
||||
// right arrow.
|
||||
"key": "ctrl+c right",
|
||||
"command": "editor.action.formatDocument",
|
||||
"when": "editorTextFocus && !editorReadonly"
|
||||
},
|
||||
{ // Duplicate selection.
|
||||
"key": "ctrl+x ctrl+d",
|
||||
"command": "editor.action.duplicateSelection"
|
||||
},
|
||||
{ // Duplicate selection.
|
||||
//
|
||||
// This is a workaround for ctrl+d not working globally as forward delete in
|
||||
// all input fields. This relies on Karabiner-Elements to remap ctrl+d to
|
||||
// forward delete.
|
||||
"key": "ctrl+x delete",
|
||||
"command": "editor.action.duplicateSelection"
|
||||
},
|
||||
{ // Rename thing at point.
|
||||
"key": "ctrl+c ctrl+.",
|
||||
"command": "editor.action.rename",
|
||||
"when": "editorHasRenameProvider && editorTextFocus && !editorReadonly"
|
||||
},
|
||||
{ // Indent line
|
||||
"key": "ctrl+c ]",
|
||||
"command": "editor.action.indentLines",
|
||||
"when": "editorTextFocus && !editorReadonly"
|
||||
},
|
||||
{ // Indent line
|
||||
"key": "alt+]",
|
||||
"command": "editor.action.indentLines",
|
||||
"when": "editorTextFocus && !editorReadonly"
|
||||
},
|
||||
{ // Outdent line
|
||||
"key": "ctrl+c [",
|
||||
"command": "editor.action.outdentLines",
|
||||
"when": "editorTextFocus && !editorReadonly"
|
||||
},
|
||||
{ // Outdent line
|
||||
"key": "alt+[",
|
||||
"command": "editor.action.outdentLines",
|
||||
"when": "editorTextFocus && !editorReadonly"
|
||||
},
|
||||
{ // Move lines up in editor.
|
||||
"key": "alt+p",
|
||||
"command": "editor.action.moveLinesUpAction",
|
||||
"when": "editorTextFocus && !editorReadonly"
|
||||
},
|
||||
{ // Move lines down in editor.
|
||||
"key": "alt+n",
|
||||
"command": "editor.action.moveLinesDownAction",
|
||||
"when": "editorTextFocus && !editorReadonly"
|
||||
},
|
||||
{ // Move lines down in editor.
|
||||
//
|
||||
// This is a workaround for alt+n not working in VSCode. Relies on
|
||||
// Karabiner-Elements to remap alt+n to cmd+alt+down.
|
||||
"key": "cmd+alt+down",
|
||||
"command": "editor.action.moveLinesDownAction",
|
||||
"when": "editorTextFocus && !editorReadonly"
|
||||
},
|
||||
{ // Move cell up in notebook editor.
|
||||
"key": "alt+p",
|
||||
"command": "notebook.cell.moveUp",
|
||||
"when": "notebookEditorFocused && !inputFocus"
|
||||
},
|
||||
{ // Move cell down in notebook editor.
|
||||
"key": "alt+n",
|
||||
"command": "notebook.cell.moveDown",
|
||||
"when": "notebookEditorFocused && !inputFocus"
|
||||
},
|
||||
{ // Move cell down in notebook editor.
|
||||
//
|
||||
// This is a workaround for alt+n not working in VSCode. Relies on
|
||||
// Karabiner-Elements to remap alt+n to cmd+alt+down.
|
||||
"key": "cmd+alt+down",
|
||||
"command": "notebook.cell.moveDown",
|
||||
"when": "notebookEditorFocused && !inputFocus"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Expand region
|
||||
// ===========================================================================
|
||||
// Extension:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=letrieu.expand-region
|
||||
//
|
||||
{ // Expand selection.
|
||||
"key": "alt+.",
|
||||
"command": "expand_region",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
{ // Shrink/contract selection.
|
||||
"key": "alt+,",
|
||||
"command": "undo_expand_region",
|
||||
"when": "editorHasSelection && editorTextFocus"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Multi-cursor
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Select all highlights.
|
||||
"key": "shift+cmd+a",
|
||||
"command": "editor.action.selectHighlights",
|
||||
"when": "editorFocus"
|
||||
},
|
||||
{ // Disable default insert cursor above keybinding.
|
||||
"key": "alt+cmd+up",
|
||||
"command": "-editor.action.insertCursorAbove",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
{ // Insert cursor above.
|
||||
"key": "alt+m",
|
||||
"command": "editor.action.insertCursorAbove",
|
||||
"when": "editorTextFocus && !editorHasSelection"
|
||||
},
|
||||
{ // Add selection to previous find match when editor has selection.
|
||||
"key": "alt+m",
|
||||
"command": "emacs-mcx.addSelectionToPreviousFindMatch",
|
||||
"when": "editorTextFocus && editorHasSelection"
|
||||
},
|
||||
{ // Disable default insert cursor below keybinding.
|
||||
"key": "alt+cmd+down",
|
||||
"command": "-editor.action.insertCursorBelow",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
{ // Insert cursor below when editor has no selection.
|
||||
"key": "alt+/",
|
||||
"command": "editor.action.insertCursorBelow",
|
||||
"when": "editorTextFocus && !editorHasSelection"
|
||||
},
|
||||
{ // Add selection to next find match when editor has selection.
|
||||
"key": "alt+/",
|
||||
"command": "emacs-mcx.addSelectionToNextFindMatch",
|
||||
"when": "editorTextFocus && editorHasSelection"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Completion
|
||||
// ===========================================================================
|
||||
//
|
||||
{
|
||||
"key": "alt+shift+f",
|
||||
"command": "editor.action.inlineSuggest.acceptNextWord"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Testing
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Run current file.
|
||||
"key": "ctrl+c , v",
|
||||
"command": "macros.runTestCurrentFile",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
{ // Run with coverage for current file.
|
||||
"key": "ctrl+c , ctrl+v",
|
||||
"command": "macros.runTestCoverageCurrentFile",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
{ // Run at cursor.
|
||||
"key": "ctrl+c , s",
|
||||
"command": "macros.runTestAtCursor",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
{ // Run with coverage at cursor.
|
||||
"key": "ctrl+c , ctrl+s",
|
||||
"command": "macros.runTestCoverageAtCursor",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
{ // Run all tests.
|
||||
"key": "ctrl+c , a",
|
||||
"command": "macros.runTestAll",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
{ // Run with coverage for all tests.
|
||||
"key": "ctrl+c , ctrl+a",
|
||||
"command": "macros.runTestCoverageAll",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
{ // Re-run last run.
|
||||
"key": "ctrl+c , l",
|
||||
"command": "macros.runTestReRunLastRun",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
{ // Re-run with coverage for last run.
|
||||
"key": "ctrl+c , ctrl+l",
|
||||
"command": "macros.runTestCoverageLastRun",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
{ // Re-run failed tests.
|
||||
"key": "ctrl+c , f",
|
||||
"command": "macros.runTestReRunFailTests",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
{ // Debug failed tests.
|
||||
"key": "ctrl+c , ctrl+f",
|
||||
"command": "macros.runTestDebugFailTests",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
{ // Debug failed tests.
|
||||
//
|
||||
// This is a workaround for ctrl+f not working globally as right arrow in
|
||||
// all input fields. This relies on Karabiner-Elements to remap ctrl+f to
|
||||
// right arrow.
|
||||
"key": "ctrl+c , right",
|
||||
"command": "macros.runTestDebugFailTests",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
{ // Debug last run.
|
||||
"key": "ctrl+c , d",
|
||||
"command": "macros.runTestDebugLastRun",
|
||||
"when": "editorTextFocus"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Documentation
|
||||
// ===========================================================================
|
||||
//
|
||||
{ // Show documentation for symbol at cursor.
|
||||
"key": "ctrl+c d",
|
||||
"command": "editor.action.showHover"
|
||||
},
|
||||
{ // Show documentation for symbol at cursor.
|
||||
"key": "ctrl+c ctrl+d",
|
||||
"command": "editor.action.triggerParameterHints"
|
||||
},
|
||||
{ // Show documentation for symbol at cursor.
|
||||
//
|
||||
// This is a workaround for ctrl+d not working globally as forward delete in
|
||||
// all input fields. Hence we rebind ctrl+d to forward delete, meaning any
|
||||
// keybindings that use ctrl+d need to be updated to use delete aswell.
|
||||
"key": "ctrl+c delete",
|
||||
"command": "editor.action.triggerParameterHints"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: edamagit
|
||||
// ===========================================================================
|
||||
// Extension URL:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=kahole.magit
|
||||
//
|
||||
{ // Open magit status.
|
||||
"key": "ctrl+x g",
|
||||
"command": "magit.status"
|
||||
},
|
||||
{ // Disable default open magit status keybinding.
|
||||
"key": "alt+x g",
|
||||
"command": "-magit.status"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: GitHub
|
||||
// ===========================================================================
|
||||
// Extensions:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=GitHub.remotehub
|
||||
// - https://marketplace.visualstudio.com/items?itemName=github.vscode-github-actions
|
||||
// - https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github
|
||||
// - https://marketplace.visualstudio.com/items?itemName=ziyasal.vscode-open-in-github
|
||||
//
|
||||
{
|
||||
"key": "ctrl+c g",
|
||||
"command": "extension.openInGitHub"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Project Manager
|
||||
// ===========================================================================
|
||||
// Extension URL:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=alefragnani.project-manager
|
||||
//
|
||||
{ // List projects.
|
||||
"key": "ctrl+z ctrl+s",
|
||||
"command": "projectManager.listProjects"
|
||||
},
|
||||
{ // Disable default list projects keybinding.
|
||||
"key": "alt+cmd+p",
|
||||
"command": "-projectManager.listProjects"
|
||||
},
|
||||
{
|
||||
"key": "ctrl+z ctrl+;",
|
||||
"command": "projectManager.listProjectsNewWindow"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: dired
|
||||
// ===========================================================================
|
||||
// Extension URL:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=rrudi.vscode-dired
|
||||
//
|
||||
{ // Open dired.
|
||||
"key": "ctrl+x ctrl+j",
|
||||
"command": "extension.dired.open",
|
||||
"when": "editorTextFocus && !inDebugRepl"
|
||||
},
|
||||
{ // Disable default open dired keybinding.
|
||||
"key": "ctrl+x f",
|
||||
"command": "-extension.dired.open",
|
||||
"when": "editorTextFocus && !inDebugRepl"
|
||||
},
|
||||
{ // Create directory.
|
||||
"key": "c",
|
||||
"command": "extension.dired.createDir",
|
||||
"when": "dired.open && !findWidgetVisible && !inQuickOpen"
|
||||
},
|
||||
{ // Disable default create directory keybinding.
|
||||
"key": "shift+=",
|
||||
"command": "-extension.dired.createDir",
|
||||
"when": "dired.open && !findWidgetVisible && !inQuickOpen"
|
||||
},
|
||||
{ // Go up directory.
|
||||
"key": "ctrl+l",
|
||||
"command": "extension.dired.goUpDir",
|
||||
"when": "dired.open && !findWidgetVisible && !inQuickOpen"
|
||||
},
|
||||
{ // Disable default go up directory keybinding.
|
||||
"key": "shift+b",
|
||||
"command": "-extension.dired.goUpDir",
|
||||
"when": "dired.open && !findWidgetVisible && !inQuickOpen"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: swiper
|
||||
// ===========================================================================
|
||||
// Extension URL:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=wenhoujx.swiper
|
||||
//
|
||||
{ // Swiper word at cursor.
|
||||
"key": "alt+r",
|
||||
"command": "swiper.swiper-word-at-cursor"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Makefile task runner
|
||||
// ===========================================================================
|
||||
// Extension URL:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=carlos-algms.make-task-provider
|
||||
//
|
||||
{ // Run target.
|
||||
"key": "ctrl+c enter",
|
||||
"command": "make-task-provider.runTarget"
|
||||
}
|
||||
]
|
||||
574
cursor/settings.json
Normal file
574
cursor/settings.json
Normal file
@@ -0,0 +1,574 @@
|
||||
{
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Appearance
|
||||
// ===========================================================================
|
||||
//
|
||||
// Dark/Light mode detection
|
||||
"window.autoDetectColorScheme": true,
|
||||
"window.systemColorTheme": "auto",
|
||||
//
|
||||
// Theme
|
||||
"workbench.colorTheme": "One Dark Pro",
|
||||
"workbench.iconTheme": "material-icon-theme",
|
||||
"workbench.preferredDarkColorTheme": "One Dark Pro",
|
||||
"workbench.preferredLightColorTheme": "Solarized Light",
|
||||
//
|
||||
// One Dark Pro theme settings
|
||||
"oneDarkPro.vivid": true,
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Window
|
||||
// ===========================================================================
|
||||
//
|
||||
"window.commandCenter": true,
|
||||
"window.customTitleBarVisibility": "auto",
|
||||
"window.nativeFullScreen": false, // Does not work with nativeTabs enabled.
|
||||
"window.nativeTabs": true,
|
||||
"window.title": "${rootName}${separator}${profileName}",
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Cursor (Text Editor)
|
||||
// ===========================================================================
|
||||
//
|
||||
"cursor.aipreview.enabled": true,
|
||||
"cursor.cpp.enablePartialAccepts": true,
|
||||
"cursor.diffs.useCharacterLevelDiffs": true,
|
||||
"cursor.terminal.usePreviewBox": true,
|
||||
"cursor.general.enableShadowWorkspace": true,
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Windsurf (Text Editor)
|
||||
// ===========================================================================
|
||||
//
|
||||
"windsurf.autocompleteSpeed": "fast",
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Editor
|
||||
// ===========================================================================
|
||||
//
|
||||
// Font
|
||||
"editor.fontFamily": "'Menlo Nerd Font Mono', 'Menlo Nerd Font', Menlo, Monaco, 'Courier New', monospace",
|
||||
"editor.fontLigatures": false,
|
||||
"editor.fontWeight": "normal",
|
||||
"editor.fontSize": 12,
|
||||
//
|
||||
// Cursor
|
||||
"editor.cursorSurroundingLines": 5,
|
||||
//
|
||||
// Whitespace
|
||||
"editor.renderWhitespace": "boundary",
|
||||
//
|
||||
// Formatting
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnSaveMode": "file",
|
||||
//
|
||||
// Rulers
|
||||
"editor.rulers": [
|
||||
80,
|
||||
100,
|
||||
120
|
||||
],
|
||||
//
|
||||
// Semantic Highlighting
|
||||
"editor.semanticHighlighting.enabled": true,
|
||||
//
|
||||
// Minimap
|
||||
"editor.minimap.enabled": true,
|
||||
"editor.minimap.showSlider": "always",
|
||||
//
|
||||
// Modified Tabs
|
||||
"workbench.editor.highlightModifiedTabs": true,
|
||||
//
|
||||
// Accessibility
|
||||
"editor.accessibilitySupport": "off",
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Workbench
|
||||
// ===========================================================================
|
||||
//
|
||||
// Activity Bar
|
||||
"workbench.activityBar.location": "top",
|
||||
"workbench.activityBar.orientation": "horizontal",
|
||||
//
|
||||
// Command Palette
|
||||
"workbench.commandPalette.history": 250,
|
||||
"workbench.commandPalette.preserveInput": true,
|
||||
//
|
||||
// Hover
|
||||
"workbench.hover.delay": 200,
|
||||
//
|
||||
// Local History
|
||||
"workbench.localHistory.maxFileEntries": 250,
|
||||
"workbench.localHistory.maxFileSize": 512,
|
||||
//
|
||||
// Tree
|
||||
"workbench.tree.indent": 18,
|
||||
"workbench.tree.renderIndentGuides": "always",
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Explorer
|
||||
// ===========================================================================
|
||||
//
|
||||
"explorer.sortOrder": "mixed",
|
||||
"explorer.sortOrderLexicographicOptions": "unicode",
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Files
|
||||
// ===========================================================================
|
||||
//
|
||||
// Associations
|
||||
"files.associations": {
|
||||
"gitconfig": "gitconfig",
|
||||
"gitignore": "gitignore"
|
||||
},
|
||||
//
|
||||
// Encoding
|
||||
"files.autoGuessEncoding": true,
|
||||
//
|
||||
// Formatting
|
||||
"files.insertFinalNewline": true,
|
||||
"files.trimFinalNewlines": true,
|
||||
"files.trimTrailingWhitespace": true,
|
||||
//
|
||||
// Read-only
|
||||
"files.readonlyFromPermissions": true,
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Git
|
||||
// ===========================================================================
|
||||
//
|
||||
"git.blame.editorDecoration.enabled": false,
|
||||
"scm.defaultViewMode": "tree",
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Diffs
|
||||
// ===========================================================================
|
||||
//
|
||||
"diffEditor.ignoreTrimWhitespace": false,
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Terminal
|
||||
// ===========================================================================
|
||||
//
|
||||
"terminal.integrated.allowChords": false,
|
||||
"terminal.integrated.macOptionIsMeta": true,
|
||||
"terminal.integrated.persistentSessionScrollback": 1000,
|
||||
"terminal.integrated.scrollback": 50000,
|
||||
"terminal.integrated.sendKeybindingsToShell": true,
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Awesome Emacs Keybindings
|
||||
// ===========================================================================
|
||||
// Extension:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=tuttieee.emacs-mcx
|
||||
//
|
||||
"emacs-mcx.emacsLikeTab": false, // Done via custom keybinding instead.
|
||||
"emacs-mcx.killRingMax": 120,
|
||||
"emacs-mcx.markRingMax": 32,
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: File Browser
|
||||
// ===========================================================================
|
||||
// Extension:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=bodil.file-browser
|
||||
//
|
||||
"file-browser.hideDotfiles": false,
|
||||
"file-browser.labelIgnoredFiles": true,
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Project Manager
|
||||
// ===========================================================================
|
||||
// Extension:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=alefragnani.project-manager
|
||||
//
|
||||
"projectManager.git.baseFolders": [
|
||||
"~/Projects",
|
||||
"~/.dotfiles",
|
||||
"~/.config"
|
||||
],
|
||||
"projectManager.git.ignoredFolders": [
|
||||
"node_modules",
|
||||
"out",
|
||||
"typings",
|
||||
"test",
|
||||
".haxelib",
|
||||
"tmp",
|
||||
"vendor",
|
||||
"straight",
|
||||
"elpaca"
|
||||
],
|
||||
"projectManager.any.ignoredFolders": [
|
||||
"node_modules",
|
||||
"out",
|
||||
"typings",
|
||||
"test",
|
||||
"tmp",
|
||||
"vendor",
|
||||
"straight",
|
||||
"elpaca"
|
||||
],
|
||||
"projectManager.hg.ignoredFolders": [
|
||||
"node_modules",
|
||||
"out",
|
||||
"typings",
|
||||
"test",
|
||||
".haxelib",
|
||||
"straight",
|
||||
"elpaca"
|
||||
],
|
||||
"projectManager.svn.ignoredFolders": [
|
||||
"node_modules",
|
||||
"out",
|
||||
"typings",
|
||||
"test",
|
||||
"straight",
|
||||
"elpaca"
|
||||
],
|
||||
"projectManager.vscode.ignoredFolders": [
|
||||
"node_modules",
|
||||
"out",
|
||||
"typings",
|
||||
"test",
|
||||
"straight",
|
||||
"elpaca"
|
||||
],
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: GitHub
|
||||
// ===========================================================================
|
||||
// Extensions:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github
|
||||
// - https://marketplace.visualstudio.com/items?itemName=GitHub.remotehub
|
||||
//
|
||||
"githubRepositories.autoFetch.enabled": false,
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Mise (https://mise.jdx.dev/)
|
||||
// ===========================================================================
|
||||
// Extension:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=hverlin.mise-vscode
|
||||
//
|
||||
"mise.updateOpenTerminalsEnvAutomatically": true,
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Hex editor
|
||||
// ===========================================================================
|
||||
// Extension:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=ms-vscode.hexeditor
|
||||
//
|
||||
"workbench.editor.defaultBinaryEditor": "hexEditor.hexedit",
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Go
|
||||
// ===========================================================================
|
||||
// Extensions:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=golang.go
|
||||
// - https://marketplace.visualstudio.com/items?itemName=gofenix.go-lines
|
||||
//
|
||||
"go-lines.lineLength": 120,
|
||||
"go.coverOnSingleTest": true,
|
||||
"go.coverShowCounts": true,
|
||||
"go.formatTool": "gofumpt",
|
||||
"go.inlayHints.constantValues": true,
|
||||
"go.lintOnSave": "workspace",
|
||||
"go.lintTool": "golangci-lint",
|
||||
"go.testExplorer.packageDisplayMode": "nested",
|
||||
"go.testExplorer.showDynamicSubtestsInEditor": true,
|
||||
"go.testFlags": [
|
||||
"-count=1"
|
||||
],
|
||||
"go.useLanguageServer": true,
|
||||
"gopls": {
|
||||
"ui.diagnostic.analyses": {
|
||||
"shadow": true
|
||||
},
|
||||
"ui.diagnostic.staticcheck": true
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: JSON
|
||||
// ===========================================================================
|
||||
//
|
||||
"[json]": {
|
||||
"editor.insertSpaces": true,
|
||||
"editor.tabSize": 2
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Lua
|
||||
// ===========================================================================
|
||||
// Extensions:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=sumneko.lua
|
||||
//
|
||||
"Lua.codeLens.enable": true,
|
||||
"Lua.diagnostics.globals": [
|
||||
// Hammerspoon
|
||||
"hs",
|
||||
"spoon"
|
||||
],
|
||||
"Lua.diagnostics.workspaceEvent": "OnChange",
|
||||
"Lua.hint.enable": true,
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Ruby
|
||||
// ===========================================================================
|
||||
// Extensions:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=Shopify.ruby-extensions-pack
|
||||
// - https://marketplace.visualstudio.com/items?itemName=connorshea.vscode-ruby-test-adapter
|
||||
//
|
||||
"[ruby]": {
|
||||
"editor.defaultFormatter": "Shopify.ruby-lsp",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnType": true,
|
||||
"editor.insertSpaces": true,
|
||||
"editor.tabSize": 2
|
||||
},
|
||||
// Ruby Test Explorer
|
||||
"rubyTestExplorer.logpanel": false,
|
||||
// Use mise to execute ruby test explorer bundler commands to ensure correct
|
||||
// version of Ruby is used.
|
||||
"rubyTestExplorer.minitestCommand": "mise x -- bundle exec rake",
|
||||
"rubyTestExplorer.rspecCommand": "mise x -- bundle exec rspec",
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Shellscript
|
||||
// ===========================================================================
|
||||
// Extensions:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=foxundermoon.shell-format
|
||||
//
|
||||
"[shellscript]": {
|
||||
"editor.tabSize": 2,
|
||||
"editor.insertSpaces": true
|
||||
},
|
||||
"[sh]": {
|
||||
"editor.tabSize": 2,
|
||||
"editor.insertSpaces": true
|
||||
},
|
||||
"[zsh]": {
|
||||
"editor.tabSize": 2,
|
||||
"editor.insertSpaces": true
|
||||
},
|
||||
"shellformat.useEditorConfig": true,
|
||||
"shellformat.flag": "-i 2 -ci -sr",
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: YAML
|
||||
// ===========================================================================
|
||||
// Extensions:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml
|
||||
// - https://marketplace.visualstudio.com/items?itemName=arahata.linter-actionlint
|
||||
//
|
||||
"redhat.telemetry.enabled": false,
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Makefile
|
||||
// ===========================================================================
|
||||
// Extensions:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=carlos-algms.make-task-provider
|
||||
//
|
||||
"makefile.configureOnOpen": false,
|
||||
"make-task-provider.telemetry": false,
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Sort Lines
|
||||
// ===========================================================================
|
||||
// Extensions:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=Tyriar.sort-lines
|
||||
//
|
||||
"sortLines.filterBlankLines": true,
|
||||
"sortLines.ignoreUnselectedLastLine": true,
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: vscode-color-picker
|
||||
// ===========================================================================
|
||||
// Extension:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=AntiAntiSepticeye.vscode-color-picker
|
||||
//
|
||||
"vscode-color-picker.languages": [
|
||||
"css",
|
||||
"go",
|
||||
"javascript",
|
||||
"less",
|
||||
"postcss",
|
||||
"python",
|
||||
"ruby",
|
||||
"sass",
|
||||
"scss",
|
||||
"sss",
|
||||
"stylus",
|
||||
"svg",
|
||||
"typescript",
|
||||
"xml"
|
||||
],
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Run on Save callbacks
|
||||
// ===========================================================================
|
||||
// Extension:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=emeraldwalk.RunOnSave
|
||||
//
|
||||
"emeraldwalk.runonsave": {
|
||||
"commands": [
|
||||
{ // Automatically chmod +x script files (first two bytes are `#!`).
|
||||
"match": ".*",
|
||||
"cmd": "if [ ! -x \"${file}\" ] && head -n 1 \"${file}\" | grep -q '^#!'; then echo \"Marking ${relativeFile} as executable...\" && chmod +x \"${file}\"; fi"
|
||||
}
|
||||
]
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Command aliases
|
||||
// ===========================================================================
|
||||
//
|
||||
"command aliases": {
|
||||
// Sort Lines.
|
||||
// Extension: https://marketplace.visualstudio.com/items?itemName=Tyriar.sort-lines
|
||||
"sortLines.sortLines": "sl"
|
||||
},
|
||||
//
|
||||
// ===========================================================================
|
||||
// MARK: Macros
|
||||
// ===========================================================================
|
||||
// Extension:
|
||||
// - https://marketplace.visualstudio.com/items?itemName=ctf0.macros
|
||||
//
|
||||
"macros.list": {
|
||||
//
|
||||
// cycleSpacing is a basic emulation Emacs' built-in cycle-spacing command.
|
||||
// It doesn't actually cycle spacing, but it performs the first step which
|
||||
// is to replace all spacing surrounding the cursor with a single space.
|
||||
//
|
||||
"cycleSpacing": [
|
||||
"emacs-mcx.deleteHorizontalSpace",
|
||||
{
|
||||
"command": "type",
|
||||
"args": {
|
||||
"text": " "
|
||||
}
|
||||
}
|
||||
],
|
||||
//
|
||||
// Run test macros which re-focus back into the editor after being
|
||||
// triggered. The test commands changes focus to the Test Results panel, and
|
||||
// no settings I found avoids this. Hence these macros trigger relevant test
|
||||
// running commands and then switches focus back to the editor.
|
||||
//
|
||||
// The 1 ms delay between the running tests and switch focus back allows for
|
||||
// the Test Results panel to appear and steal focus before we try and focus
|
||||
// back into the editor. Without the delay the focus commands runs before
|
||||
// Test Results appear and steal focus.
|
||||
//
|
||||
"runTestCurrentFile": [
|
||||
"testing.runCurrentFile",
|
||||
{
|
||||
"command": "$delay",
|
||||
"args": {
|
||||
"delay": 1
|
||||
}
|
||||
},
|
||||
"workbench.action.focusActiveEditorGroup"
|
||||
],
|
||||
"runTestCoverageCurrentFile": [
|
||||
"testing.coverageCurrentFile",
|
||||
{
|
||||
"command": "$delay",
|
||||
"args": {
|
||||
"delay": 1
|
||||
}
|
||||
},
|
||||
"workbench.action.focusActiveEditorGroup"
|
||||
],
|
||||
"runTestAtCursor": [
|
||||
"testing.runAtCursor",
|
||||
{
|
||||
"command": "$delay",
|
||||
"args": {
|
||||
"delay": 1
|
||||
}
|
||||
},
|
||||
"workbench.action.focusActiveEditorGroup"
|
||||
],
|
||||
"runTestCoverageAtCursor": [
|
||||
"testing.coverageAtCursor",
|
||||
{
|
||||
"command": "$delay",
|
||||
"args": {
|
||||
"delay": 1
|
||||
}
|
||||
},
|
||||
"workbench.action.focusActiveEditorGroup"
|
||||
],
|
||||
"runTestAll": [
|
||||
"testing.runAll",
|
||||
{
|
||||
"command": "$delay",
|
||||
"args": {
|
||||
"delay": 1
|
||||
}
|
||||
},
|
||||
"workbench.action.focusActiveEditorGroup"
|
||||
],
|
||||
"runTestCoverageAll": [
|
||||
"testing.coverageAll",
|
||||
{
|
||||
"command": "$delay",
|
||||
"args": {
|
||||
"delay": 1
|
||||
}
|
||||
},
|
||||
"workbench.action.focusActiveEditorGroup"
|
||||
],
|
||||
"runTestReRunLastRun": [
|
||||
"testing.reRunLastRun",
|
||||
{
|
||||
"command": "$delay",
|
||||
"args": {
|
||||
"delay": 1
|
||||
}
|
||||
},
|
||||
"workbench.action.focusActiveEditorGroup"
|
||||
],
|
||||
"runTestCoverageLastRun": [
|
||||
"testing.coverageLastRun",
|
||||
{
|
||||
"command": "$delay",
|
||||
"args": {
|
||||
"delay": 1
|
||||
}
|
||||
},
|
||||
"workbench.action.focusActiveEditorGroup"
|
||||
],
|
||||
"runTestReRunFailTests": [
|
||||
"testing.reRunFailTests",
|
||||
{
|
||||
"command": "$delay",
|
||||
"args": {
|
||||
"delay": 1
|
||||
}
|
||||
},
|
||||
"workbench.action.focusActiveEditorGroup"
|
||||
],
|
||||
"runTestDebugFailTests": [
|
||||
"testing.debugFailTests",
|
||||
{
|
||||
"command": "$delay",
|
||||
"args": {
|
||||
"delay": 1
|
||||
}
|
||||
},
|
||||
"workbench.action.focusActiveEditorGroup"
|
||||
],
|
||||
"runTestDebugLastRun": [
|
||||
"testing.debugLastRun",
|
||||
{
|
||||
"command": "$delay",
|
||||
"args": {
|
||||
"delay": 1
|
||||
}
|
||||
},
|
||||
"workbench.action.focusActiveEditorGroup"
|
||||
]
|
||||
}
|
||||
}
|
||||
506
cursor/setup.sh
Executable file
506
cursor/setup.sh
Executable file
@@ -0,0 +1,506 @@
|
||||
#! /usr/bin/env bash
|
||||
|
||||
# ==============================================================================
|
||||
# Settings
|
||||
# ==============================================================================
|
||||
|
||||
# Default editor to configure (cursor, vscode, or vscode-insiders)
|
||||
SETUP_EDITOR="cursor"
|
||||
|
||||
# List of config files to symlink from current directory.
|
||||
CONFIG_SOURCES=(
|
||||
"settings.json"
|
||||
"keybindings.json"
|
||||
"snippets"
|
||||
)
|
||||
|
||||
# Detect current script directory.
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Get extensions lockfile path for current editor
|
||||
get_extensions_lock() {
|
||||
echo "${SCRIPT_DIR}/extensions.${SETUP_EDITOR}.lock"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# Help
|
||||
# ==============================================================================
|
||||
|
||||
show_help() {
|
||||
cat << EOF
|
||||
Usage: $(basename "$0") EDITOR COMMAND [OPTIONS]
|
||||
|
||||
Editors:
|
||||
cursor, c Cursor editor
|
||||
vscode, code, vsc, v Visual Studio Code
|
||||
vscode-insiders, vsci, i Visual Studio Code Insiders
|
||||
windsurf, surf, w Windsurf editor
|
||||
|
||||
Commands:
|
||||
config, conf Create symlinks for editor config files
|
||||
dump-extensions, dump Export installed editor extensions to extensions.txt
|
||||
extensions, ext Install editor extensions from extensions.txt
|
||||
|
||||
Options:
|
||||
--latest When used with extensions command, installs the
|
||||
latest version of each extension instead of the
|
||||
exact version from the lock file
|
||||
|
||||
Description:
|
||||
This script manages editor configuration files and extensions.
|
||||
It can create symlinks for settings, keybindings, and snippets,
|
||||
as well as dump extension lock files and install extensions from them.
|
||||
EOF
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# Functions
|
||||
# ==============================================================================
|
||||
|
||||
# Determine editor config directory
|
||||
editor_config_dir() {
|
||||
case "$(uname -s)" in
|
||||
"Darwin")
|
||||
case "${SETUP_EDITOR}" in
|
||||
"cursor")
|
||||
echo "${HOME}/Library/Application Support/Cursor/User"
|
||||
;;
|
||||
"vscode")
|
||||
echo "${HOME}/Library/Application Support/Code/User"
|
||||
;;
|
||||
"vscode-insiders")
|
||||
echo "${HOME}/Library/Application Support/Code - Insiders/User"
|
||||
;;
|
||||
"windsurf")
|
||||
echo "${HOME}/Library/Application Support/Windsurf/User"
|
||||
;;
|
||||
*)
|
||||
echo "Error: Invalid editor '${SETUP_EDITOR}' for macOS"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
"Linux")
|
||||
case "${SETUP_EDITOR}" in
|
||||
"cursor")
|
||||
echo "${HOME}/.config/Cursor/User"
|
||||
;;
|
||||
"vscode")
|
||||
echo "${HOME}/.config/Code/User"
|
||||
;;
|
||||
"vscode-insiders")
|
||||
echo "${HOME}/.config/Code - Insiders/User"
|
||||
;;
|
||||
"windsurf")
|
||||
echo "${HOME}/.config/Windsurf/User"
|
||||
;;
|
||||
*)
|
||||
echo "Error: Invalid editor '${SETUP_EDITOR}' for Linux"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "Error: Unsupported operating system"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Backup and symlink
|
||||
backup_and_link() {
|
||||
local source="$1"
|
||||
local target="$2"
|
||||
local real_target
|
||||
local real_source
|
||||
|
||||
# Check if target already exists
|
||||
if [[ -e "${target}" ]]; then
|
||||
# If it's a symlink, check if it points to the same location
|
||||
if [[ -L "${target}" ]]; then
|
||||
real_target="$(readlink -f "${target}")"
|
||||
real_source="$(readlink -f "${source}")"
|
||||
if [[ "${real_target}" == "${real_source}" ]]; then
|
||||
echo "Skipping ${target} - already linked to ${source}"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Backing up existing ${target} to ${target}.bak"
|
||||
mv "${target}" "${target}.bak"
|
||||
fi
|
||||
|
||||
# Create symlink
|
||||
echo "Creating symlink for ${source} to ${target}"
|
||||
ln -s "${source}" "${target}"
|
||||
}
|
||||
|
||||
# Create symlinks
|
||||
do_symlink() {
|
||||
# Create editor config directory if it doesn't exist
|
||||
local config_dir
|
||||
config_dir="$(editor_config_dir)"
|
||||
|
||||
mkdir -p "${config_dir}"
|
||||
for path in "${CONFIG_SOURCES[@]}"; do
|
||||
backup_and_link "${SCRIPT_DIR}/${path}" "${config_dir}/${path}"
|
||||
done
|
||||
|
||||
echo "Symlink setup complete!"
|
||||
}
|
||||
|
||||
# Find the editor CLI command
|
||||
find_editor_cmd() {
|
||||
local editor_cmd=""
|
||||
local possible_commands=()
|
||||
|
||||
case "${SETUP_EDITOR}" in
|
||||
"cursor")
|
||||
# Set possible Cursor CLI command locations
|
||||
possible_commands=(
|
||||
"cursor"
|
||||
"/Applications/Cursor.app/Contents/Resources/app/bin/cursor"
|
||||
"${HOME}/Applications/Cursor.app/Contents/Resources/app/bin/cursor"
|
||||
)
|
||||
;;
|
||||
"vscode")
|
||||
# Set possible VSCode CLI command locations
|
||||
possible_commands=(
|
||||
"code"
|
||||
"/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code"
|
||||
"${HOME}/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code"
|
||||
)
|
||||
;;
|
||||
"vscode-insiders")
|
||||
# Set possible VSCode Insiders CLI command locations
|
||||
possible_commands=(
|
||||
"code-insiders"
|
||||
"/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code"
|
||||
"${HOME}/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code"
|
||||
)
|
||||
;;
|
||||
"windsurf")
|
||||
# Set possible Windsurf CLI command locations
|
||||
possible_commands=(
|
||||
"windsurf"
|
||||
"/Applications/Windsurf.app/Contents/Resources/app/bin/windsurf"
|
||||
"${HOME}/Applications/Windsurf.app/Contents/Resources/app/bin/windsurf"
|
||||
)
|
||||
;;
|
||||
*)
|
||||
echo "Error: Invalid editor '${SETUP_EDITOR}'"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check for the command in all possible locations
|
||||
for cmd in "${possible_commands[@]}"; do
|
||||
echo "Checking ${cmd}" >&2
|
||||
if command -v "${cmd}" > /dev/null 2>&1; then
|
||||
editor_cmd="${cmd}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -z "${editor_cmd}" ]]; then
|
||||
echo "Error: ${SETUP_EDITOR} command not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "${editor_cmd}"
|
||||
}
|
||||
|
||||
# Dump installed extensions to extensions.lock
|
||||
do_dump_extensions() {
|
||||
local editor_cmd
|
||||
editor_cmd="$(find_editor_cmd)"
|
||||
local current_date
|
||||
current_date="$(date)"
|
||||
local extensions_lock
|
||||
extensions_lock="$(get_extensions_lock)"
|
||||
|
||||
{
|
||||
echo "# ${SETUP_EDITOR} Extensions"
|
||||
echo "# Generated on ${current_date}"
|
||||
echo
|
||||
"${editor_cmd}" --list-extensions --show-versions
|
||||
} > "${extensions_lock}"
|
||||
|
||||
echo "Extensions list dumped to ${extensions_lock}"
|
||||
}
|
||||
|
||||
# Global variable to cache installed extensions
|
||||
_INSTALLED_EXTENSIONS=""
|
||||
|
||||
# Check if extension is already installed, ignoring version
|
||||
is_extension_installed() {
|
||||
local editor_cmd="$1"
|
||||
local extension="$2"
|
||||
|
||||
# Build cache if not already built
|
||||
if [[ -z "${_INSTALLED_EXTENSIONS}" ]]; then
|
||||
_INSTALLED_EXTENSIONS="$("${editor_cmd}" --list-extensions --show-versions)"
|
||||
fi
|
||||
|
||||
# Check if extension exists in cached list
|
||||
echo "${_INSTALLED_EXTENSIONS}" | grep -q "^${extension}@"
|
||||
}
|
||||
|
||||
# Install an extension directly using the marketplace
|
||||
install_extension_direct() {
|
||||
local editor_cmd="$1"
|
||||
local extension="$2"
|
||||
local version="$3"
|
||||
local use_latest="$4"
|
||||
local result=0
|
||||
|
||||
if [[ "${use_latest}" == "true" ]]; then
|
||||
echo "Installing ${extension} (latest version)"
|
||||
if ! "${editor_cmd}" --install-extension "${extension}"; then
|
||||
echo "Warning: Direct install failed for ${extension}"
|
||||
result=1
|
||||
fi
|
||||
else
|
||||
echo "Installing ${extension}@${version}"
|
||||
if ! "${editor_cmd}" --install-extension "${extension}@${version}"; then
|
||||
echo "Warning: Direct install failed for ${extension}@${version}"
|
||||
result=1
|
||||
fi
|
||||
fi
|
||||
|
||||
return ${result}
|
||||
}
|
||||
|
||||
# Install an extension via downloading .vsix file
|
||||
install_extension_via_vsix() {
|
||||
local editor_cmd="$1"
|
||||
local extension="$2"
|
||||
local version="$3"
|
||||
local use_latest="$4"
|
||||
local extensions_cache_dir="$5"
|
||||
local result=0
|
||||
|
||||
local publisher_id="${extension%%.*}"
|
||||
local extension_id="${extension#*.}"
|
||||
local vsix_path=""
|
||||
local vsix_url=""
|
||||
local install_version=""
|
||||
|
||||
if [[ "${use_latest}" == "true" ]]; then
|
||||
# In latest mode, we need to first query the marketplace to get the latest version
|
||||
echo "Finding latest version for ${extension}..."
|
||||
|
||||
# Query the VS Marketplace API to get the extension metadata
|
||||
local metadata_url="https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery"
|
||||
local temp_metadata="${extensions_cache_dir}/metadata-${extension}.json"
|
||||
|
||||
# Create extensions directory if it doesn't exist
|
||||
mkdir -p "${extensions_cache_dir}"
|
||||
|
||||
# Create a JSON request payload to query for the extension details
|
||||
local request_data='{
|
||||
"filters": [
|
||||
{
|
||||
"criteria": [
|
||||
{ "filterType": 7, "value": "'${extension}'" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"flags": 2
|
||||
}'
|
||||
|
||||
# Query the marketplace for extension metadata
|
||||
if ! curl --silent --compressed -X POST -H "Content-Type: application/json" -H "Accept: application/json; api-version=7.2-preview.1" -d "${request_data}" "${metadata_url}" > "${temp_metadata}"; then
|
||||
echo "Warning: Failed to query metadata for ${extension}"
|
||||
rm -f "${temp_metadata}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Extract the latest version from the response
|
||||
if command -v jq > /dev/null 2>&1; then
|
||||
# If jq is available, use it to parse JSON
|
||||
install_version=$(jq -r '.results[0].extensions[0].versions[0].version' "${temp_metadata}" 2> /dev/null)
|
||||
else
|
||||
# Fallback to grep/sed for basic extraction if jq is not available
|
||||
install_version=$(grep -o '"version":"[^"]*"' "${temp_metadata}" | head -1 | sed 's/"version":"//;s/"//' 2> /dev/null)
|
||||
fi
|
||||
|
||||
# Clean up metadata file
|
||||
rm -f "${temp_metadata}"
|
||||
|
||||
# If we couldn't extract a version, use original version as fallback
|
||||
if [[ -z "${install_version}" || "${install_version}" == "null" ]]; then
|
||||
echo "Warning: Could not determine latest version, falling back to lock file version"
|
||||
install_version="${version}"
|
||||
else
|
||||
echo "Latest version of ${extension} is ${install_version}"
|
||||
fi
|
||||
|
||||
# Set up the download path and URL for the specific version we found
|
||||
vsix_path="${extensions_cache_dir}/${extension}@${install_version}.vsix"
|
||||
vsix_url="https://marketplace.visualstudio.com/_apis/public/gallery/publishers/${publisher_id}/vsextensions/${extension_id}/${install_version}/vspackage"
|
||||
else
|
||||
# In strict mode, use the exact version from the lock file
|
||||
echo "Installing ${extension}@${version} via .vsix"
|
||||
vsix_path="${extensions_cache_dir}/${extension}@${version}.vsix"
|
||||
vsix_url="https://marketplace.visualstudio.com/_apis/public/gallery/publishers/${publisher_id}/vsextensions/${extension_id}/${version}/vspackage"
|
||||
install_version="${version}"
|
||||
fi
|
||||
|
||||
# Create extensions directory if it doesn't exist
|
||||
mkdir -p "${extensions_cache_dir}"
|
||||
|
||||
# Download the .vsix file
|
||||
echo "Downloading ${extension}@${install_version}.vsix..."
|
||||
echo " - URL: ${vsix_url}"
|
||||
if ! curl --compressed -L -o "${vsix_path}" "${vsix_url}"; then
|
||||
echo "Warning: Failed to download ${extension}@${install_version}.vsix"
|
||||
rm -f "${vsix_path}" # Clean up potential partial downloads
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Install the extension from .vsix file
|
||||
echo "Installing extension from ${vsix_path}"
|
||||
if ! "${editor_cmd}" --install-extension "${vsix_path}"; then
|
||||
echo "Warning: Failed to install ${extension}@${install_version} from .vsix"
|
||||
result=1
|
||||
fi
|
||||
|
||||
# Clean up the .vsix file after installation attempt
|
||||
rm -f "${vsix_path}"
|
||||
|
||||
return ${result}
|
||||
}
|
||||
|
||||
# Install extensions from extensions.lock
|
||||
do_install_extensions() {
|
||||
local editor_cmd
|
||||
editor_cmd="$(find_editor_cmd)"
|
||||
local extensions_cache_dir="${SCRIPT_DIR}/cache/extensions"
|
||||
local extensions_lock
|
||||
extensions_lock="$(get_extensions_lock)"
|
||||
local use_latest="${1:-false}"
|
||||
|
||||
if [[ ! -f "${extensions_lock}" ]]; then
|
||||
echo "Error: ${extensions_lock} not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Process each extension
|
||||
while IFS= read -r line; do
|
||||
if [[ -n "${line}" && ! "${line}" =~ ^[[:space:]]*# ]]; then
|
||||
extension="${line%@*}"
|
||||
version="${line#*@}"
|
||||
|
||||
# Check if already installed with correct version
|
||||
if is_extension_installed "${editor_cmd}" "${extension}"; then
|
||||
echo "Extension ${extension} is already installed, skipping"
|
||||
continue
|
||||
fi
|
||||
|
||||
# For Cursor we need to download and install from .vsix file, as
|
||||
# installation via ID fails with a signature verification error.
|
||||
if [[ "${SETUP_EDITOR}" == "cursor" ]]; then
|
||||
install_extension_via_vsix "${editor_cmd}" "${extension}" "${version}" "${use_latest}" "${extensions_cache_dir}"
|
||||
continue
|
||||
fi
|
||||
|
||||
if ! install_extension_direct "${editor_cmd}" "${extension}" "${version}" "${use_latest}"; then
|
||||
echo "Direct installation failed, trying .vsix download method..."
|
||||
install_extension_via_vsix "${editor_cmd}" "${extension}" "${version}" "${use_latest}" "${extensions_cache_dir}"
|
||||
fi
|
||||
fi
|
||||
done < "${extensions_lock}"
|
||||
|
||||
# Clean up extensions directory if empty
|
||||
rmdir "${extensions_cache_dir}" 2> /dev/null || true
|
||||
echo "Extensions installation complete!"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# Main
|
||||
# ==============================================================================
|
||||
|
||||
main() {
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "Error: No editor specified"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $# -lt 2 ]]; then
|
||||
echo "Error: No command specified"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set editor from first argument
|
||||
editor="$(echo "${1}" | tr '[:upper:]' '[:lower:]')"
|
||||
case "${editor}" in
|
||||
"vscode" | "code" | "vsc" | "v")
|
||||
SETUP_EDITOR="vscode"
|
||||
;;
|
||||
"vscode-insiders" | "code-insiders" | "insiders" | "vsci" | "i")
|
||||
SETUP_EDITOR="vscode-insiders"
|
||||
;;
|
||||
"cursor" | "c")
|
||||
SETUP_EDITOR="cursor"
|
||||
;;
|
||||
"windsurf" | "wind" | "surf" | "w")
|
||||
SETUP_EDITOR="windsurf"
|
||||
;;
|
||||
*)
|
||||
echo "Error: Unsupported editor '${editor}'"
|
||||
echo "Supported editors: cursor, vscode (vsc), vscode-insiders (vsci), windsurf (wind)"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Get command from second argument
|
||||
local command="${2}"
|
||||
shift 2
|
||||
|
||||
# Default values for options
|
||||
local use_latest="false"
|
||||
|
||||
# Parse additional options
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--latest)
|
||||
use_latest="true"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "Error: Unknown option '$1'"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Handle commands
|
||||
case "${command}" in
|
||||
"config" | "conf")
|
||||
do_symlink
|
||||
;;
|
||||
"dump-extensions" | "dump")
|
||||
do_dump_extensions
|
||||
;;
|
||||
"extensions" | "ext")
|
||||
do_install_extensions "${use_latest}"
|
||||
;;
|
||||
"")
|
||||
echo "Error: No command provided"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
echo "Error: Unknown command '${command}'"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Run main function.
|
||||
main "$@"
|
||||
78
cursor/snippets/go.json
Normal file
78
cursor/snippets/go.json
Normal file
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"println": {
|
||||
"prefix": "pd",
|
||||
"body": [
|
||||
"fmt.Println($0)",
|
||||
],
|
||||
"description": "fmt.Println(...)"
|
||||
},
|
||||
"debug print": {
|
||||
"prefix": "ppd",
|
||||
"body": [
|
||||
"fmt.Printf(\"$1: %#v\\n\", $1)$0",
|
||||
],
|
||||
"description": "fmt.Printf(\"...: %+v\\n\", ...)"
|
||||
},
|
||||
"printf": {
|
||||
"prefix": "pf",
|
||||
"body": [
|
||||
"fmt.Printf(${1:format}, ${2:a ...any})$0",
|
||||
],
|
||||
"description": "fmt.Printf(..., ...)"
|
||||
},
|
||||
"sprintf": {
|
||||
"prefix": "spf",
|
||||
"body": [
|
||||
"fmt.Sprintf(${1:format}, ${2:a ...any})$0",
|
||||
],
|
||||
"description": "fmt.Sprintf(..., ...)"
|
||||
},
|
||||
"test func": {
|
||||
"prefix": "tf",
|
||||
"body": [
|
||||
"func Test${1:Name}(t *testing.T) {",
|
||||
"\ttests := []struct {",
|
||||
"\t\tname string",
|
||||
"\t\t$0",
|
||||
"\t}{",
|
||||
"\t\t{",
|
||||
"\t\t\tname: \"\",",
|
||||
"\t\t},",
|
||||
"\t}",
|
||||
"\tfor _, tt := range tests {",
|
||||
"\t\tt.Run(tt.name, func(t *testing.T) {",
|
||||
"\t\t\t",
|
||||
"\t\t})",
|
||||
"\t}",
|
||||
"}"
|
||||
],
|
||||
"description": "func Test...(t *testing.T) { ... }"
|
||||
},
|
||||
"test table": {
|
||||
"prefix": "tt",
|
||||
"body": [
|
||||
"tests := []struct {",
|
||||
"\tname string",
|
||||
"\t$0",
|
||||
"}{",
|
||||
"\t{",
|
||||
"\t\tname: \"\",",
|
||||
"\t},",
|
||||
"}"
|
||||
],
|
||||
"description": "tests := []struct { ... }"
|
||||
},
|
||||
"benchmark func": {
|
||||
"prefix": "bf",
|
||||
"body": [
|
||||
"func Benchmark${1:Name}(b *testing.B) {",
|
||||
"\t$0",
|
||||
"",
|
||||
"\tfor n := 0; n < b.N; n++ {",
|
||||
"\t\t",
|
||||
"\t}",
|
||||
"}"
|
||||
],
|
||||
"description": "func Benchmark...(b *testing.B) { ... }"
|
||||
}
|
||||
}
|
||||
36
cursor/snippets/ruby.json
Normal file
36
cursor/snippets/ruby.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
// Place your snippets for ruby here. Each snippet is defined under a snippet name and has a prefix, body and
|
||||
// description. The prefix is what is used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
|
||||
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. Placeholders with the
|
||||
// same ids are connected.
|
||||
// Example:
|
||||
// "Print to console": {
|
||||
// "prefix": "log",
|
||||
// "body": [
|
||||
// "console.log('$1');",
|
||||
// "$2"
|
||||
// ],
|
||||
// "description": "Log output to console"
|
||||
// }
|
||||
"print": {
|
||||
"prefix": "pd",
|
||||
"body": [
|
||||
"puts \"\\n>>>>>> ${1:name}: ${2:#{$1${3:.inspect}\\}}\\n\"$0"
|
||||
],
|
||||
"description": "puts \">>>>> ...: #{....inspect}\""
|
||||
},
|
||||
"pretty print": {
|
||||
"prefix": "ppd",
|
||||
"body": [
|
||||
"puts \"\\n>>>>>> ${1:name}:\"; pp $1$0"
|
||||
],
|
||||
"description": "puts \">>>>> ... \"; pp ..."
|
||||
},
|
||||
"byebug": {
|
||||
"prefix": "bug",
|
||||
"body": [
|
||||
"require 'byebug'; byebug$0"
|
||||
],
|
||||
"description": "require 'byebug'; byebug"
|
||||
}
|
||||
}
|
||||
4
default.nix
Normal file
4
default.nix
Normal file
@@ -0,0 +1,4 @@
|
||||
let
|
||||
flake = builtins.getFlake "git+file://${builtins.toString ./.}";
|
||||
in
|
||||
flake.packages.${builtins.currentSystem}.default
|
||||
27
flake.lock
generated
Normal file
27
flake.lock
generated
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1768302833,
|
||||
"narHash": "sha256-h5bRFy9bco+8QcK7rGoOiqMxMbmn21moTACofNLRMP4=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "61db79b0c6b838d9894923920b612048e1201926",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
36
flake.nix
Normal file
36
flake.nix
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
description = "Global packages for dotfiles";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||
};
|
||||
|
||||
outputs =
|
||||
{ self, nixpkgs }:
|
||||
let
|
||||
systems = [
|
||||
"x86_64-darwin"
|
||||
"aarch64-darwin"
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
];
|
||||
forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f system);
|
||||
in
|
||||
{
|
||||
packages = forAllSystems (
|
||||
system:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
in
|
||||
{
|
||||
default = pkgs.buildEnv {
|
||||
name = "dotfiles-packages";
|
||||
paths = [
|
||||
pkgs.nil
|
||||
pkgs.nixfmt
|
||||
];
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -2,25 +2,25 @@
|
||||
font-family: "Menlo Nerd Font Mono";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url("Menlo Regular Nerd Font Complete Mono.ttf") format("truetype");
|
||||
src: url("MenloNerdFontMono-Regular.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Menlo Nerd Font Mono";
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: url("Menlo Italic Nerd Font Complete Mono.ttf") format("truetype");
|
||||
src: url("MenloNerdFontMono-Italic.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Menlo Nerd Font Mono";
|
||||
font-weight: 700;
|
||||
src: url("Menlo Bold Nerd Font Complete Mono.ttf") format("truetype");
|
||||
src: url("MenloNerdFontMono-Bold.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Menlo Nerd Font Mono";
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: url("Menlo Bold Italic Nerd Font Complete Mono.ttf") format("truetype");
|
||||
src: url("MenloNerdFontMono-BoldItalic.ttf") format("truetype");
|
||||
}
|
||||
|
||||
BIN
fonts/Menlo Nerd Font Mono.ttc
Normal file
BIN
fonts/Menlo Nerd Font Mono.ttc
Normal file
Binary file not shown.
26
fonts/Menlo Nerd Font Propo.css
Normal file
26
fonts/Menlo Nerd Font Propo.css
Normal file
@@ -0,0 +1,26 @@
|
||||
@font-face {
|
||||
font-family: "Menlo Nerd Font Propo";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url("MenloNerdFontPropo-Regular.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Menlo Nerd Font Propo";
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: url("MenloNerdFontPropo-Italic.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Menlo Nerd Font Propo";
|
||||
font-weight: 700;
|
||||
src: url("MenloNerdFontPropo-Bold.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Menlo Nerd Font Propo";
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: url("MenloNerdFontPropo-BoldItalic.ttf") format("truetype");
|
||||
}
|
||||
BIN
fonts/Menlo Nerd Font Propo.ttc
Normal file
BIN
fonts/Menlo Nerd Font Propo.ttc
Normal file
Binary file not shown.
26
fonts/Menlo Nerd Font.css
Normal file
26
fonts/Menlo Nerd Font.css
Normal file
@@ -0,0 +1,26 @@
|
||||
@font-face {
|
||||
font-family: "Menlo Nerd Font";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url("MenloNerdFont-Regular.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Menlo Nerd Font";
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: url("MenloNerdFont-Italic.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Menlo Nerd Font";
|
||||
font-weight: 700;
|
||||
src: url("MenloNerdFont-Bold.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Menlo Nerd Font";
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: url("MenloNerdFont-BoldItalic.ttf") format("truetype");
|
||||
}
|
||||
BIN
fonts/Menlo Nerd Font.ttc
Normal file
BIN
fonts/Menlo Nerd Font.ttc
Normal file
Binary file not shown.
Binary file not shown.
BIN
fonts/MenloNerdFont-Bold.ttf
Normal file
BIN
fonts/MenloNerdFont-Bold.ttf
Normal file
Binary file not shown.
BIN
fonts/MenloNerdFont-BoldItalic.ttf
Normal file
BIN
fonts/MenloNerdFont-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
fonts/MenloNerdFont-Italic.ttf
Normal file
BIN
fonts/MenloNerdFont-Italic.ttf
Normal file
Binary file not shown.
BIN
fonts/MenloNerdFont-Regular.ttf
Normal file
BIN
fonts/MenloNerdFont-Regular.ttf
Normal file
Binary file not shown.
BIN
fonts/MenloNerdFontMono-Bold.ttf
Normal file
BIN
fonts/MenloNerdFontMono-Bold.ttf
Normal file
Binary file not shown.
BIN
fonts/MenloNerdFontMono-BoldItalic.ttf
Normal file
BIN
fonts/MenloNerdFontMono-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
fonts/MenloNerdFontMono-Italic.ttf
Normal file
BIN
fonts/MenloNerdFontMono-Italic.ttf
Normal file
Binary file not shown.
BIN
fonts/MenloNerdFontMono-Regular.ttf
Normal file
BIN
fonts/MenloNerdFontMono-Regular.ttf
Normal file
Binary file not shown.
BIN
fonts/MenloNerdFontPropo-Bold.ttf
Normal file
BIN
fonts/MenloNerdFontPropo-Bold.ttf
Normal file
Binary file not shown.
BIN
fonts/MenloNerdFontPropo-BoldItalic.ttf
Normal file
BIN
fonts/MenloNerdFontPropo-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
fonts/MenloNerdFontPropo-Italic.ttf
Normal file
BIN
fonts/MenloNerdFontPropo-Italic.ttf
Normal file
Binary file not shown.
BIN
fonts/MenloNerdFontPropo-Regular.ttf
Normal file
BIN
fonts/MenloNerdFontPropo-Regular.ttf
Normal file
Binary file not shown.
1
gitattributes
Normal file
1
gitattributes
Normal file
@@ -0,0 +1 @@
|
||||
merge=mergiraf
|
||||
33
gitconfig
33
gitconfig
@@ -7,6 +7,7 @@
|
||||
[tag]
|
||||
gpgsign = true
|
||||
[core]
|
||||
attributesfile = ~/.gitattributes
|
||||
excludesfile = ~/.gitignore
|
||||
[color]
|
||||
status = auto
|
||||
@@ -16,6 +17,10 @@
|
||||
whitespace = nowarn
|
||||
[push]
|
||||
default = simple
|
||||
[pull]
|
||||
rebase = true
|
||||
[rerere]
|
||||
enabled = true
|
||||
[alias]
|
||||
a = add
|
||||
ai = add -i
|
||||
@@ -39,10 +44,8 @@
|
||||
pgp-on = config commit.gpgsign true
|
||||
pgp-off = config commit.gpgsign false
|
||||
tree = log --all --graph --decorate --oneline --simplify-by-decoration
|
||||
[pull]
|
||||
rebase = true
|
||||
[difftool "Kaleidoscope"]
|
||||
cmd = ksdiff-wrapper git \"$LOCAL\" \"$REMOTE\"
|
||||
cmd = ksdiff --partial-changeset --relative-path \"$MERGED\" -- \"$LOCAL\" \"$REMOTE\"
|
||||
[difftool]
|
||||
prompt = false
|
||||
[diff]
|
||||
@@ -60,10 +63,30 @@
|
||||
smudge = git hawser smudge %f
|
||||
required = true
|
||||
[filter "lfs"]
|
||||
clean = git-lfs clean %f
|
||||
smudge = git-lfs smudge %f
|
||||
clean = git-lfs clean -- %f
|
||||
smudge = git-lfs smudge -- %f
|
||||
required = true
|
||||
process = git-lfs filter-process
|
||||
[include]
|
||||
path = ~/.gitconfig_private
|
||||
[init]
|
||||
defaultBranch = main
|
||||
[gitlab]
|
||||
user = jimeh
|
||||
[credential "https://github.com"]
|
||||
# helper = !~/.dotfiles/bin/gh-git-credential-helper
|
||||
helper = !cd ~/ && op plugin run -- gh auth git-credential
|
||||
[credential "https://gist.github.com"]
|
||||
# helper = !~/.dotfiles/bin/gh-git-credential-helper
|
||||
helper = !cd ~/ && op plugin run -- gh auth git-credential
|
||||
[merge "mergiraf"]
|
||||
name = mergiraf
|
||||
driver = mergiraf merge --git %O %A %B -s %S -x %X -y %Y -p %P -l %L
|
||||
[mergetool "Kaleidoscope"]
|
||||
cmd = ksdiff --merge --output \"$MERGED\" --base \"$BASE\" -- \"$LOCAL\" --snapshot \"$REMOTE\" --snapshot
|
||||
trustExitCode = true
|
||||
[gitbutler]
|
||||
aiModelProvider = anthropic
|
||||
aiAnthropicKeyOption = butlerAPI
|
||||
signCommits = true
|
||||
aiOpenAIKeyOption = butlerAPI
|
||||
|
||||
29
gitignore
29
gitignore
@@ -1,19 +1,34 @@
|
||||
**/._zinit/*
|
||||
**/.agents/drafts/
|
||||
**/.agents/plans/
|
||||
**/.agents/reviews/
|
||||
**/.claude/drafts/
|
||||
**/.claude/plans/
|
||||
**/.claude/reviews/
|
||||
**/.claude/settings.local.json
|
||||
**/.claude/worktrees/
|
||||
**/.vscode/settings.json
|
||||
**/.vscode/settings.local.json
|
||||
**/chart/preprod-values.yaml
|
||||
**/chart/production-values.yaml
|
||||
**/chart/staging-values.yaml
|
||||
**/log/*.bz2
|
||||
**/log/*.gz
|
||||
**/test/dummy/log/*.bz2
|
||||
**/test/dummy/log/*.gz
|
||||
**/vendor/bundle
|
||||
.AppleDouble
|
||||
.DS_Store
|
||||
._zinit/*
|
||||
.bin
|
||||
.bundle
|
||||
.byebug_history
|
||||
.dir-locals.el
|
||||
.envrc
|
||||
.mise.*local.toml
|
||||
.projectile
|
||||
.stfolder
|
||||
.stignore
|
||||
.vagrant
|
||||
.vscode
|
||||
.zinitrc.zsh
|
||||
log/*.bz2
|
||||
log/*.gz
|
||||
mise.*local.toml
|
||||
routes.txt
|
||||
test/dummy/log/*.bz2
|
||||
test/dummy/log/*.gz
|
||||
vendor/bundle
|
||||
|
||||
77
gnome/extensions/gtile-dconf-settings.conf
Normal file
77
gnome/extensions/gtile-dconf-settings.conf
Normal file
@@ -0,0 +1,77 @@
|
||||
[/]
|
||||
action-contract-bottom=['<Control><Alt><Super>i']
|
||||
action-contract-left=@as []
|
||||
action-contract-right=['<Control><Alt><Super>j']
|
||||
action-contract-top=@as []
|
||||
action-expand-bottom=['<Control><Alt><Super>k']
|
||||
action-expand-right=['<Control><Alt><Super>l']
|
||||
action-move-down=['<Control><Alt>k']
|
||||
action-move-left=['<Control><Alt>j']
|
||||
action-move-next-monitor=['<Control><Super>period']
|
||||
action-move-right=['<Control><Alt>l']
|
||||
action-move-up=['<Control><Alt>i']
|
||||
contract-down=['<Shift>i']
|
||||
contract-right=['<Shift>j']
|
||||
expand-down=['<Shift>k']
|
||||
expand-right=['<Shift>l']
|
||||
grid-sizes='30x20'
|
||||
insets-primary-bottom=1
|
||||
insets-primary-left=4
|
||||
insets-primary-right=4
|
||||
insets-primary-top=4
|
||||
insets-secondary-bottom=1
|
||||
insets-secondary-left=4
|
||||
insets-secondary-right=4
|
||||
insets-secondary-top=4
|
||||
move-down=['k']
|
||||
move-left=['j']
|
||||
move-next-monitor=['n']
|
||||
move-right=['l']
|
||||
move-up=['i']
|
||||
preset-resize-1=['<Control><Super>j']
|
||||
preset-resize-10=['<Control><Alt>backslash']
|
||||
preset-resize-11=['<Control><Super>backslash']
|
||||
preset-resize-12=['<Control><Alt>apostrophe']
|
||||
preset-resize-13=['<Control><Super>apostrophe']
|
||||
preset-resize-14=['<Control><Alt>semicolon']
|
||||
preset-resize-15=['<Control><Super>semicolon']
|
||||
preset-resize-16=['<Control><Super>h']
|
||||
preset-resize-17=@as []
|
||||
preset-resize-18=@as []
|
||||
preset-resize-19=@as []
|
||||
preset-resize-2=['<Control><Super>l']
|
||||
preset-resize-21=@as []
|
||||
preset-resize-22=@as []
|
||||
preset-resize-23=@as []
|
||||
preset-resize-24=@as []
|
||||
preset-resize-25=@as []
|
||||
preset-resize-26=@as []
|
||||
preset-resize-27=@as []
|
||||
preset-resize-28=@as []
|
||||
preset-resize-29=@as []
|
||||
preset-resize-3=['<Control><Super>i']
|
||||
preset-resize-4=['<Control><Super>k']
|
||||
preset-resize-5=['<Control><Alt>u']
|
||||
preset-resize-6=['<Control><Alt>o']
|
||||
preset-resize-7=['<Control><Super>u']
|
||||
preset-resize-8=['<Control><Super>o']
|
||||
preset-resize-9=['<Control><Alt><Super>backslash']
|
||||
resize1='30x20 1:1 15:20'
|
||||
resize10='30x20 10:1 21:20'
|
||||
resize11='30x20 8:1 23:20'
|
||||
resize12='30x20 7:1 24:20'
|
||||
resize13='30x20 6:1 25:20'
|
||||
resize14='30x20 5:1 26:20'
|
||||
resize15='30x20 4:1 27:20'
|
||||
resize16='30x20 1:1 30:20'
|
||||
resize2='30x20 16:1 30:20'
|
||||
resize3='30x20 1:1 30:10'
|
||||
resize4='30x20 1:11 30:20'
|
||||
resize5='30x20 1:1 10:20'
|
||||
resize6='30x20 21:1 30:20'
|
||||
resize7='30x20 1:1 18:20'
|
||||
resize8='30x20 13:1 30:20'
|
||||
resize9='30x20 11:1 20:20'
|
||||
show-grid-lines=true
|
||||
show-toggle-tiling=['<Control><Super>1']
|
||||
window-spacing=2
|
||||
10
hammerspoon/.luarc.json
Normal file
10
hammerspoon/.luarc.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json",
|
||||
"diagnostics.globals": [
|
||||
"hs",
|
||||
"spoon"
|
||||
],
|
||||
"workspace.library": [
|
||||
"/Applications/Hammerspoon.app/Contents/Resources/extensions/hs"
|
||||
]
|
||||
}
|
||||
@@ -68,5 +68,6 @@ endef
|
||||
#
|
||||
|
||||
$(eval $(call dep-file,inspect.lua,"https://github.com/kikito/inspect.lua/raw/v3.1.0/inspect.lua"))
|
||||
$(eval $(call dep-spoon,RoundedCorners,"https://github.com/Hammerspoon/Spoons/raw/master/Spoons/RoundedCorners.spoon.zip"))
|
||||
$(eval $(call dep-spoon,HeadphoneAutoPause,"https://github.com/Hammerspoon/Spoons/raw/master/Spoons/HeadphoneAutoPause.spoon.zip"))
|
||||
$(eval $(call dep-spoon,RoundedCorners,"https://github.com/Hammerspoon/Spoons/raw/master/Spoons/RoundedCorners.spoon.zip"))
|
||||
$(eval $(call dep-spoon,URLDispatcher,"https://github.com/Hammerspoon/Spoons/raw/master/Spoons/URLDispatcher.spoon.zip"))
|
||||
|
||||
400
hammerspoon/Spoons/URLDispatcher.spoon/docs.json
Normal file
400
hammerspoon/Spoons/URLDispatcher.spoon/docs.json
Normal file
@@ -0,0 +1,400 @@
|
||||
[
|
||||
{
|
||||
"Command": [],
|
||||
"Constant": [],
|
||||
"Constructor": [],
|
||||
"Deprecated": [],
|
||||
"Field": [],
|
||||
"Function": [],
|
||||
"Method": [
|
||||
{
|
||||
"def": "URLDispatcher:dispatchURL(scheme, host, params, fullUrl, senderPid)",
|
||||
"desc": "Dispatch a URL to an application according to the defined `url_patterns`.",
|
||||
"doc": "Dispatch a URL to an application according to the defined `url_patterns`.\n\nParameters:\n * scheme - A string containing the URL scheme (i.e. \"http\")\n * host - A string containing the host requested (e.g. \"www.hammerspoon.org\")\n * params - A table containing the key/value pairs of all the URL parameters\n * fullURL - A string containing the full, original URL. This is the only parameter used in this implementation.\n * senderPID - An integer containing the PID of the application that opened the URL, if available (otherwise -1)\n\nNotes:\n * The parameters (follow to the [httpCallback](http://www.hammerspoon.org/docs/hs.urlevent.html#httpCallback) specification)",
|
||||
"examples": [],
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "188",
|
||||
"name": "dispatchURL",
|
||||
"notes": [
|
||||
" * The parameters (follow to the [httpCallback](http://www.hammerspoon.org/docs/hs.urlevent.html#httpCallback) specification)"
|
||||
],
|
||||
"parameters": [
|
||||
" * scheme - A string containing the URL scheme (i.e. \"http\")",
|
||||
" * host - A string containing the host requested (e.g. \"www.hammerspoon.org\")",
|
||||
" * params - A table containing the key/value pairs of all the URL parameters",
|
||||
" * fullURL - A string containing the full, original URL. This is the only parameter used in this implementation.",
|
||||
" * senderPID - An integer containing the PID of the application that opened the URL, if available (otherwise -1)"
|
||||
],
|
||||
"returns": [],
|
||||
"signature": "URLDispatcher:dispatchURL(scheme, host, params, fullUrl, senderPid)",
|
||||
"stripped_doc": "",
|
||||
"type": "Method"
|
||||
},
|
||||
{
|
||||
"def": "URLDispatcher:start()",
|
||||
"desc": "Start dispatching URLs according to the rules",
|
||||
"doc": "Start dispatching URLs according to the rules\n\nParameters:\n * None",
|
||||
"examples": [],
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "312",
|
||||
"name": "start",
|
||||
"notes": [],
|
||||
"parameters": [
|
||||
" * None"
|
||||
],
|
||||
"returns": [],
|
||||
"signature": "URLDispatcher:start()",
|
||||
"stripped_doc": "",
|
||||
"type": "Method"
|
||||
}
|
||||
],
|
||||
"Variable": [
|
||||
{
|
||||
"def": "URLDispatcher.decode_slack_redir_urls",
|
||||
"desc": "If true, handle Slack-redir URLs to apply the rule on the destination URL. Defaults to `true`",
|
||||
"doc": "If true, handle Slack-redir URLs to apply the rule on the destination URL. Defaults to `true`",
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "30",
|
||||
"name": "decode_slack_redir_urls",
|
||||
"signature": "URLDispatcher.decode_slack_redir_urls",
|
||||
"stripped_doc": "",
|
||||
"type": "Variable"
|
||||
},
|
||||
{
|
||||
"def": "URLDispatcher.default_handler",
|
||||
"desc": "Default URL handler (Defaults to `\"com.apple.Safari\"`)",
|
||||
"doc": "Default URL handler (Defaults to `\"com.apple.Safari\"`)\n\nNotes:\nCan be a string containing the Bundle ID of an application, or a function\nthat takes one argument, and which will be invoked with the URL to open.",
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "21",
|
||||
"name": "default_handler",
|
||||
"notes": [
|
||||
"Can be a string containing the Bundle ID of an application, or a function",
|
||||
"that takes one argument, and which will be invoked with the URL to open."
|
||||
],
|
||||
"signature": "URLDispatcher.default_handler",
|
||||
"stripped_doc": "",
|
||||
"type": "Variable"
|
||||
},
|
||||
{
|
||||
"def": "URLDispatcher.logger",
|
||||
"desc": "Logger object used within the Spoon. Can be accessed to set the default log",
|
||||
"doc": "Logger object used within the Spoon. Can be accessed to set the default log\nlevel for the messages coming from the Spoon.\n\nNotes:\nExample: `spoon.URLDispatcher.logger.setLogLevel(\"debug\")`",
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "99",
|
||||
"name": "logger",
|
||||
"notes": [
|
||||
"Example: `spoon.URLDispatcher.logger.setLogLevel(\"debug\")`"
|
||||
],
|
||||
"signature": "URLDispatcher.logger",
|
||||
"stripped_doc": "level for the messages coming from the Spoon.",
|
||||
"type": "Variable"
|
||||
},
|
||||
{
|
||||
"def": "URLDispatcher.pat_files",
|
||||
"desc": "Internal variable containing a table where the pattern lists read from files are kept indexed by file name, and automatically updated.",
|
||||
"doc": "Internal variable containing a table where the pattern lists read from files are kept indexed by file name, and automatically updated.",
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "114",
|
||||
"name": "pat_files",
|
||||
"signature": "URLDispatcher.pat_files",
|
||||
"stripped_doc": "",
|
||||
"type": "Variable"
|
||||
},
|
||||
{
|
||||
"def": "URLDispatcher.pat_watchers",
|
||||
"desc": "Internal variable containing a table where the watchers for the pattern files are kept indexed by file name.",
|
||||
"doc": "Internal variable containing a table where the watchers for the pattern files are kept indexed by file name.",
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "119",
|
||||
"name": "pat_watchers",
|
||||
"signature": "URLDispatcher.pat_watchers",
|
||||
"stripped_doc": "",
|
||||
"type": "Variable"
|
||||
},
|
||||
{
|
||||
"def": "URLDispatcher.set_system_handler",
|
||||
"desc": "If true, URLDispatcher sets itself as system handler for http requests.",
|
||||
"doc": "If true, URLDispatcher sets itself as system handler for http requests.\nDefaults to `true`",
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "108",
|
||||
"name": "set_system_handler",
|
||||
"signature": "URLDispatcher.set_system_handler",
|
||||
"stripped_doc": "Defaults to `true`",
|
||||
"type": "Variable"
|
||||
},
|
||||
{
|
||||
"def": "URLDispatcher.url_patterns",
|
||||
"desc": "URL dispatch rules.",
|
||||
"doc": "URL dispatch rules.\n\nNotes:\n A table containing a list of dispatch rules. Rules are evaluated in the\n order they are declared. Each rule is a table with the following structure:\n `{ url-patterns, app-bundle-ID-or-function, function, app-patterns }`\n * `url-patterns` can be: (a) a single pattern as a string, (b) a table\n containing a list of strings, or (c) a string containing the path of a\n file from which the patterns will be read (if the string contains a valid\n filename it's used as a file, otherwise as a pattern). In case (c), a\n watcher will be set to automatically re-read the contents of the file\n when it changes. If a relative path is given (not starting with a \"/\"),\n then it is considered to be relative to the Hammerspoon configuration\n directory.\n * If `app-bundle-ID-or-function` is specified as a string, it is\n interpreted as a macOS application ID, and that application will be used\n to open matching URLs. If it is a function pointer, or not given but\n \"function\" is provided, it is expected to be a function that accepts a\n single argument, and it will be called with the URL.\n * If `app-patterns` is given, it should be a string or a table containing a\n pattern/list of patterns, and the rule will only be evaluated if the URL\n was opened from an application whose name matches one of those patterns.\n * Note that the patterns are [Lua patterns](https://www.lua.org/pil/20.2.html)\n and not regular expressions.\n * Defaults to an empty table, which has the effect of having all URLs\n dispatched to the `default_handler`.",
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "69",
|
||||
"name": "url_patterns",
|
||||
"notes": [
|
||||
" A table containing a list of dispatch rules. Rules are evaluated in the",
|
||||
" order they are declared. Each rule is a table with the following structure:",
|
||||
" `{ url-patterns, app-bundle-ID-or-function, function, app-patterns }`",
|
||||
" * `url-patterns` can be: (a) a single pattern as a string, (b) a table",
|
||||
" containing a list of strings, or (c) a string containing the path of a",
|
||||
" file from which the patterns will be read (if the string contains a valid",
|
||||
" filename it's used as a file, otherwise as a pattern). In case (c), a",
|
||||
" watcher will be set to automatically re-read the contents of the file",
|
||||
" when it changes. If a relative path is given (not starting with a \"/\"),",
|
||||
" then it is considered to be relative to the Hammerspoon configuration",
|
||||
" directory.",
|
||||
" * If `app-bundle-ID-or-function` is specified as a string, it is",
|
||||
" interpreted as a macOS application ID, and that application will be used",
|
||||
" to open matching URLs. If it is a function pointer, or not given but",
|
||||
" \"function\" is provided, it is expected to be a function that accepts a",
|
||||
" single argument, and it will be called with the URL.",
|
||||
" * If `app-patterns` is given, it should be a string or a table containing a",
|
||||
" pattern/list of patterns, and the rule will only be evaluated if the URL",
|
||||
" was opened from an application whose name matches one of those patterns.",
|
||||
" * Note that the patterns are [Lua patterns](https://www.lua.org/pil/20.2.html)",
|
||||
" and not regular expressions.",
|
||||
" * Defaults to an empty table, which has the effect of having all URLs",
|
||||
" dispatched to the `default_handler`."
|
||||
],
|
||||
"signature": "URLDispatcher.url_patterns",
|
||||
"stripped_doc": "",
|
||||
"type": "Variable"
|
||||
},
|
||||
{
|
||||
"def": "URLDispatcher.url_redir_decoders",
|
||||
"desc": "URL redirection decoders. Default value: empty list",
|
||||
"doc": "URL redirection decoders. Default value: empty list\n\nNotes:\nList containing optional redirection decoders (other than the known Slack\ndecoder, which is enabled by `URLDispatcher.decode_slack_redir_urls` to\napply to URLs before dispatching them. Each list element must be a list\nitself with a maximum of five elements:\n * `decoder-name`: (String) a name to identify the decoder;\n * `decoder-pattern-or-function`: (String or Function) if a string is\n given, it is used as a [Lua pattern](https://www.lua.org/pil/20.2.html)\n to match against the URL. If a function is given, it will be called with\n arguments `scheme`, `host`, `params`, `fullUrl`, `senderPid` (the same\n arguments as passed to\n [hs.urlevent.httpCallback](https://www.hammerspoon.org/docs/hs.urlevent.html#httpCallback)),\n and must return a string that contains the URL to be opened. The\n returned value will be URL-decoded according to the value of `skip-decode-url` (below).\n * `pattern-replacement`: (String) a replacement pattern to apply if a\n match is found when a decoder pattern (previous argument) is provided.\n If a decoder function is given, this argument is ignored.\n * `skip-decode-url`: (Boolean, optional) whether to skip URL-decoding of the\n resulting string (defaults to `false`, by default URLs are always decoded)\n * `source-application`: (String or Table, optional): a pattern or list of\n patterns to match against the name of the application from which the URL\n was opened. If this parameter is present, the decoder will only be\n applied when the application matches. Default is to apply the decoder\n regardless of the application.\nIf given as strings, `decoder-pattern-or-function` and `pattern-replacement`\nare passed as arguments to\n[string.gsub](https://www.lua.org/manual/5.3/manual.html#pdf-string.gsub)\napplied on the original URL.",
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "35",
|
||||
"name": "url_redir_decoders",
|
||||
"notes": [
|
||||
"List containing optional redirection decoders (other than the known Slack",
|
||||
"decoder, which is enabled by `URLDispatcher.decode_slack_redir_urls` to",
|
||||
"apply to URLs before dispatching them. Each list element must be a list",
|
||||
"itself with a maximum of five elements:",
|
||||
" * `decoder-name`: (String) a name to identify the decoder;",
|
||||
" * `decoder-pattern-or-function`: (String or Function) if a string is",
|
||||
" given, it is used as a [Lua pattern](https://www.lua.org/pil/20.2.html)",
|
||||
" to match against the URL. If a function is given, it will be called with",
|
||||
" arguments `scheme`, `host`, `params`, `fullUrl`, `senderPid` (the same",
|
||||
" arguments as passed to",
|
||||
" [hs.urlevent.httpCallback](https://www.hammerspoon.org/docs/hs.urlevent.html#httpCallback)),",
|
||||
" and must return a string that contains the URL to be opened. The",
|
||||
" returned value will be URL-decoded according to the value of `skip-decode-url` (below).",
|
||||
" * `pattern-replacement`: (String) a replacement pattern to apply if a",
|
||||
" match is found when a decoder pattern (previous argument) is provided.",
|
||||
" If a decoder function is given, this argument is ignored.",
|
||||
" * `skip-decode-url`: (Boolean, optional) whether to skip URL-decoding of the",
|
||||
" resulting string (defaults to `false`, by default URLs are always decoded)",
|
||||
" * `source-application`: (String or Table, optional): a pattern or list of",
|
||||
" patterns to match against the name of the application from which the URL",
|
||||
" was opened. If this parameter is present, the decoder will only be",
|
||||
" applied when the application matches. Default is to apply the decoder",
|
||||
" regardless of the application.",
|
||||
"If given as strings, `decoder-pattern-or-function` and `pattern-replacement`",
|
||||
"are passed as arguments to",
|
||||
"[string.gsub](https://www.lua.org/manual/5.3/manual.html#pdf-string.gsub)",
|
||||
"applied on the original URL."
|
||||
],
|
||||
"signature": "URLDispatcher.url_redir_decoders",
|
||||
"stripped_doc": "",
|
||||
"type": "Variable"
|
||||
}
|
||||
],
|
||||
"desc": "Route URLs to different applications with pattern matching",
|
||||
"doc": "Route URLs to different applications with pattern matching\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/URLDispatcher.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/URLDispatcher.spoon.zip)\n\nSets Hammerspoon as the default browser for HTTP/HTTPS links, and\ndispatches them to different apps according to the patterns defined\nin the config. If no pattern matches, `default_handler` is used.",
|
||||
"items": [
|
||||
{
|
||||
"def": "URLDispatcher.decode_slack_redir_urls",
|
||||
"desc": "If true, handle Slack-redir URLs to apply the rule on the destination URL. Defaults to `true`",
|
||||
"doc": "If true, handle Slack-redir URLs to apply the rule on the destination URL. Defaults to `true`",
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "30",
|
||||
"name": "decode_slack_redir_urls",
|
||||
"signature": "URLDispatcher.decode_slack_redir_urls",
|
||||
"stripped_doc": "",
|
||||
"type": "Variable"
|
||||
},
|
||||
{
|
||||
"def": "URLDispatcher.default_handler",
|
||||
"desc": "Default URL handler (Defaults to `\"com.apple.Safari\"`)",
|
||||
"doc": "Default URL handler (Defaults to `\"com.apple.Safari\"`)\n\nNotes:\nCan be a string containing the Bundle ID of an application, or a function\nthat takes one argument, and which will be invoked with the URL to open.",
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "21",
|
||||
"name": "default_handler",
|
||||
"notes": [
|
||||
"Can be a string containing the Bundle ID of an application, or a function",
|
||||
"that takes one argument, and which will be invoked with the URL to open."
|
||||
],
|
||||
"signature": "URLDispatcher.default_handler",
|
||||
"stripped_doc": "",
|
||||
"type": "Variable"
|
||||
},
|
||||
{
|
||||
"def": "URLDispatcher:dispatchURL(scheme, host, params, fullUrl, senderPid)",
|
||||
"desc": "Dispatch a URL to an application according to the defined `url_patterns`.",
|
||||
"doc": "Dispatch a URL to an application according to the defined `url_patterns`.\n\nParameters:\n * scheme - A string containing the URL scheme (i.e. \"http\")\n * host - A string containing the host requested (e.g. \"www.hammerspoon.org\")\n * params - A table containing the key/value pairs of all the URL parameters\n * fullURL - A string containing the full, original URL. This is the only parameter used in this implementation.\n * senderPID - An integer containing the PID of the application that opened the URL, if available (otherwise -1)\n\nNotes:\n * The parameters (follow to the [httpCallback](http://www.hammerspoon.org/docs/hs.urlevent.html#httpCallback) specification)",
|
||||
"examples": [],
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "188",
|
||||
"name": "dispatchURL",
|
||||
"notes": [
|
||||
" * The parameters (follow to the [httpCallback](http://www.hammerspoon.org/docs/hs.urlevent.html#httpCallback) specification)"
|
||||
],
|
||||
"parameters": [
|
||||
" * scheme - A string containing the URL scheme (i.e. \"http\")",
|
||||
" * host - A string containing the host requested (e.g. \"www.hammerspoon.org\")",
|
||||
" * params - A table containing the key/value pairs of all the URL parameters",
|
||||
" * fullURL - A string containing the full, original URL. This is the only parameter used in this implementation.",
|
||||
" * senderPID - An integer containing the PID of the application that opened the URL, if available (otherwise -1)"
|
||||
],
|
||||
"returns": [],
|
||||
"signature": "URLDispatcher:dispatchURL(scheme, host, params, fullUrl, senderPid)",
|
||||
"stripped_doc": "",
|
||||
"type": "Method"
|
||||
},
|
||||
{
|
||||
"def": "URLDispatcher.logger",
|
||||
"desc": "Logger object used within the Spoon. Can be accessed to set the default log",
|
||||
"doc": "Logger object used within the Spoon. Can be accessed to set the default log\nlevel for the messages coming from the Spoon.\n\nNotes:\nExample: `spoon.URLDispatcher.logger.setLogLevel(\"debug\")`",
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "99",
|
||||
"name": "logger",
|
||||
"notes": [
|
||||
"Example: `spoon.URLDispatcher.logger.setLogLevel(\"debug\")`"
|
||||
],
|
||||
"signature": "URLDispatcher.logger",
|
||||
"stripped_doc": "level for the messages coming from the Spoon.",
|
||||
"type": "Variable"
|
||||
},
|
||||
{
|
||||
"def": "URLDispatcher.pat_files",
|
||||
"desc": "Internal variable containing a table where the pattern lists read from files are kept indexed by file name, and automatically updated.",
|
||||
"doc": "Internal variable containing a table where the pattern lists read from files are kept indexed by file name, and automatically updated.",
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "114",
|
||||
"name": "pat_files",
|
||||
"signature": "URLDispatcher.pat_files",
|
||||
"stripped_doc": "",
|
||||
"type": "Variable"
|
||||
},
|
||||
{
|
||||
"def": "URLDispatcher.pat_watchers",
|
||||
"desc": "Internal variable containing a table where the watchers for the pattern files are kept indexed by file name.",
|
||||
"doc": "Internal variable containing a table where the watchers for the pattern files are kept indexed by file name.",
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "119",
|
||||
"name": "pat_watchers",
|
||||
"signature": "URLDispatcher.pat_watchers",
|
||||
"stripped_doc": "",
|
||||
"type": "Variable"
|
||||
},
|
||||
{
|
||||
"def": "URLDispatcher.set_system_handler",
|
||||
"desc": "If true, URLDispatcher sets itself as system handler for http requests.",
|
||||
"doc": "If true, URLDispatcher sets itself as system handler for http requests.\nDefaults to `true`",
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "108",
|
||||
"name": "set_system_handler",
|
||||
"signature": "URLDispatcher.set_system_handler",
|
||||
"stripped_doc": "Defaults to `true`",
|
||||
"type": "Variable"
|
||||
},
|
||||
{
|
||||
"def": "URLDispatcher:start()",
|
||||
"desc": "Start dispatching URLs according to the rules",
|
||||
"doc": "Start dispatching URLs according to the rules\n\nParameters:\n * None",
|
||||
"examples": [],
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "312",
|
||||
"name": "start",
|
||||
"notes": [],
|
||||
"parameters": [
|
||||
" * None"
|
||||
],
|
||||
"returns": [],
|
||||
"signature": "URLDispatcher:start()",
|
||||
"stripped_doc": "",
|
||||
"type": "Method"
|
||||
},
|
||||
{
|
||||
"def": "URLDispatcher.url_patterns",
|
||||
"desc": "URL dispatch rules.",
|
||||
"doc": "URL dispatch rules.\n\nNotes:\n A table containing a list of dispatch rules. Rules are evaluated in the\n order they are declared. Each rule is a table with the following structure:\n `{ url-patterns, app-bundle-ID-or-function, function, app-patterns }`\n * `url-patterns` can be: (a) a single pattern as a string, (b) a table\n containing a list of strings, or (c) a string containing the path of a\n file from which the patterns will be read (if the string contains a valid\n filename it's used as a file, otherwise as a pattern). In case (c), a\n watcher will be set to automatically re-read the contents of the file\n when it changes. If a relative path is given (not starting with a \"/\"),\n then it is considered to be relative to the Hammerspoon configuration\n directory.\n * If `app-bundle-ID-or-function` is specified as a string, it is\n interpreted as a macOS application ID, and that application will be used\n to open matching URLs. If it is a function pointer, or not given but\n \"function\" is provided, it is expected to be a function that accepts a\n single argument, and it will be called with the URL.\n * If `app-patterns` is given, it should be a string or a table containing a\n pattern/list of patterns, and the rule will only be evaluated if the URL\n was opened from an application whose name matches one of those patterns.\n * Note that the patterns are [Lua patterns](https://www.lua.org/pil/20.2.html)\n and not regular expressions.\n * Defaults to an empty table, which has the effect of having all URLs\n dispatched to the `default_handler`.",
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "69",
|
||||
"name": "url_patterns",
|
||||
"notes": [
|
||||
" A table containing a list of dispatch rules. Rules are evaluated in the",
|
||||
" order they are declared. Each rule is a table with the following structure:",
|
||||
" `{ url-patterns, app-bundle-ID-or-function, function, app-patterns }`",
|
||||
" * `url-patterns` can be: (a) a single pattern as a string, (b) a table",
|
||||
" containing a list of strings, or (c) a string containing the path of a",
|
||||
" file from which the patterns will be read (if the string contains a valid",
|
||||
" filename it's used as a file, otherwise as a pattern). In case (c), a",
|
||||
" watcher will be set to automatically re-read the contents of the file",
|
||||
" when it changes. If a relative path is given (not starting with a \"/\"),",
|
||||
" then it is considered to be relative to the Hammerspoon configuration",
|
||||
" directory.",
|
||||
" * If `app-bundle-ID-or-function` is specified as a string, it is",
|
||||
" interpreted as a macOS application ID, and that application will be used",
|
||||
" to open matching URLs. If it is a function pointer, or not given but",
|
||||
" \"function\" is provided, it is expected to be a function that accepts a",
|
||||
" single argument, and it will be called with the URL.",
|
||||
" * If `app-patterns` is given, it should be a string or a table containing a",
|
||||
" pattern/list of patterns, and the rule will only be evaluated if the URL",
|
||||
" was opened from an application whose name matches one of those patterns.",
|
||||
" * Note that the patterns are [Lua patterns](https://www.lua.org/pil/20.2.html)",
|
||||
" and not regular expressions.",
|
||||
" * Defaults to an empty table, which has the effect of having all URLs",
|
||||
" dispatched to the `default_handler`."
|
||||
],
|
||||
"signature": "URLDispatcher.url_patterns",
|
||||
"stripped_doc": "",
|
||||
"type": "Variable"
|
||||
},
|
||||
{
|
||||
"def": "URLDispatcher.url_redir_decoders",
|
||||
"desc": "URL redirection decoders. Default value: empty list",
|
||||
"doc": "URL redirection decoders. Default value: empty list\n\nNotes:\nList containing optional redirection decoders (other than the known Slack\ndecoder, which is enabled by `URLDispatcher.decode_slack_redir_urls` to\napply to URLs before dispatching them. Each list element must be a list\nitself with a maximum of five elements:\n * `decoder-name`: (String) a name to identify the decoder;\n * `decoder-pattern-or-function`: (String or Function) if a string is\n given, it is used as a [Lua pattern](https://www.lua.org/pil/20.2.html)\n to match against the URL. If a function is given, it will be called with\n arguments `scheme`, `host`, `params`, `fullUrl`, `senderPid` (the same\n arguments as passed to\n [hs.urlevent.httpCallback](https://www.hammerspoon.org/docs/hs.urlevent.html#httpCallback)),\n and must return a string that contains the URL to be opened. The\n returned value will be URL-decoded according to the value of `skip-decode-url` (below).\n * `pattern-replacement`: (String) a replacement pattern to apply if a\n match is found when a decoder pattern (previous argument) is provided.\n If a decoder function is given, this argument is ignored.\n * `skip-decode-url`: (Boolean, optional) whether to skip URL-decoding of the\n resulting string (defaults to `false`, by default URLs are always decoded)\n * `source-application`: (String or Table, optional): a pattern or list of\n patterns to match against the name of the application from which the URL\n was opened. If this parameter is present, the decoder will only be\n applied when the application matches. Default is to apply the decoder\n regardless of the application.\nIf given as strings, `decoder-pattern-or-function` and `pattern-replacement`\nare passed as arguments to\n[string.gsub](https://www.lua.org/manual/5.3/manual.html#pdf-string.gsub)\napplied on the original URL.",
|
||||
"file": "Source/URLDispatcher.spoon//init.lua",
|
||||
"lineno": "35",
|
||||
"name": "url_redir_decoders",
|
||||
"notes": [
|
||||
"List containing optional redirection decoders (other than the known Slack",
|
||||
"decoder, which is enabled by `URLDispatcher.decode_slack_redir_urls` to",
|
||||
"apply to URLs before dispatching them. Each list element must be a list",
|
||||
"itself with a maximum of five elements:",
|
||||
" * `decoder-name`: (String) a name to identify the decoder;",
|
||||
" * `decoder-pattern-or-function`: (String or Function) if a string is",
|
||||
" given, it is used as a [Lua pattern](https://www.lua.org/pil/20.2.html)",
|
||||
" to match against the URL. If a function is given, it will be called with",
|
||||
" arguments `scheme`, `host`, `params`, `fullUrl`, `senderPid` (the same",
|
||||
" arguments as passed to",
|
||||
" [hs.urlevent.httpCallback](https://www.hammerspoon.org/docs/hs.urlevent.html#httpCallback)),",
|
||||
" and must return a string that contains the URL to be opened. The",
|
||||
" returned value will be URL-decoded according to the value of `skip-decode-url` (below).",
|
||||
" * `pattern-replacement`: (String) a replacement pattern to apply if a",
|
||||
" match is found when a decoder pattern (previous argument) is provided.",
|
||||
" If a decoder function is given, this argument is ignored.",
|
||||
" * `skip-decode-url`: (Boolean, optional) whether to skip URL-decoding of the",
|
||||
" resulting string (defaults to `false`, by default URLs are always decoded)",
|
||||
" * `source-application`: (String or Table, optional): a pattern or list of",
|
||||
" patterns to match against the name of the application from which the URL",
|
||||
" was opened. If this parameter is present, the decoder will only be",
|
||||
" applied when the application matches. Default is to apply the decoder",
|
||||
" regardless of the application.",
|
||||
"If given as strings, `decoder-pattern-or-function` and `pattern-replacement`",
|
||||
"are passed as arguments to",
|
||||
"[string.gsub](https://www.lua.org/manual/5.3/manual.html#pdf-string.gsub)",
|
||||
"applied on the original URL."
|
||||
],
|
||||
"signature": "URLDispatcher.url_redir_decoders",
|
||||
"stripped_doc": "",
|
||||
"type": "Variable"
|
||||
}
|
||||
],
|
||||
"name": "URLDispatcher",
|
||||
"stripped_doc": "\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/URLDispatcher.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/URLDispatcher.spoon.zip)\n\nSets Hammerspoon as the default browser for HTTP/HTTPS links, and\ndispatches them to different apps according to the patterns defined\nin the config. If no pattern matches, `default_handler` is used.",
|
||||
"submodules": [],
|
||||
"type": "Module"
|
||||
}
|
||||
]
|
||||
330
hammerspoon/Spoons/URLDispatcher.spoon/init.lua
Normal file
330
hammerspoon/Spoons/URLDispatcher.spoon/init.lua
Normal file
@@ -0,0 +1,330 @@
|
||||
--- === URLDispatcher ===
|
||||
---
|
||||
--- Route URLs to different applications with pattern matching
|
||||
---
|
||||
--- Download: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/URLDispatcher.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/URLDispatcher.spoon.zip)
|
||||
---
|
||||
--- Sets Hammerspoon as the default browser for HTTP/HTTPS links, and
|
||||
--- dispatches them to different apps according to the patterns defined
|
||||
--- in the config. If no pattern matches, `default_handler` is used.
|
||||
|
||||
local obj={}
|
||||
obj.__index = obj
|
||||
|
||||
-- Metadata
|
||||
obj.name = "URLDispatcher"
|
||||
obj.version = "0.5"
|
||||
obj.author = "Diego Zamboni <diego@zzamboni.org>"
|
||||
obj.homepage = "https://github.com/Hammerspoon/Spoons"
|
||||
obj.license = "MIT - https://opensource.org/licenses/MIT"
|
||||
|
||||
--- URLDispatcher.default_handler
|
||||
--- Variable
|
||||
--- Default URL handler (Defaults to `"com.apple.Safari"`)
|
||||
---
|
||||
--- Notes:
|
||||
--- Can be a string containing the Bundle ID of an application, or a function
|
||||
--- that takes one argument, and which will be invoked with the URL to open.
|
||||
obj.default_handler = "com.apple.Safari"
|
||||
|
||||
--- URLDispatcher.decode_slack_redir_urls
|
||||
--- Variable
|
||||
--- If true, handle Slack-redir URLs to apply the rule on the destination URL. Defaults to `true`
|
||||
obj.decode_slack_redir_urls = true
|
||||
|
||||
--- URLDispatcher.url_redir_decoders
|
||||
--- Variable
|
||||
--- URL redirection decoders. Default value: empty list
|
||||
---
|
||||
--- Notes:
|
||||
--- List containing optional redirection decoders (other than the known Slack
|
||||
--- decoder, which is enabled by `URLDispatcher.decode_slack_redir_urls` to
|
||||
--- apply to URLs before dispatching them. Each list element must be a list
|
||||
--- itself with a maximum of five elements:
|
||||
--- * `decoder-name`: (String) a name to identify the decoder;
|
||||
--- * `decoder-pattern-or-function`: (String or Function) if a string is
|
||||
--- given, it is used as a [Lua pattern](https://www.lua.org/pil/20.2.html)
|
||||
--- to match against the URL. If a function is given, it will be called with
|
||||
--- arguments `scheme`, `host`, `params`, `fullUrl`, `senderPid` (the same
|
||||
--- arguments as passed to
|
||||
--- [hs.urlevent.httpCallback](https://www.hammerspoon.org/docs/hs.urlevent.html#httpCallback)),
|
||||
--- and must return a string that contains the URL to be opened. The
|
||||
--- returned value will be URL-decoded according to the value of `skip-decode-url` (below).
|
||||
--- * `pattern-replacement`: (String) a replacement pattern to apply if a
|
||||
--- match is found when a decoder pattern (previous argument) is provided.
|
||||
--- If a decoder function is given, this argument is ignored.
|
||||
--- * `skip-decode-url`: (Boolean, optional) whether to skip URL-decoding of the
|
||||
--- resulting string (defaults to `false`, by default URLs are always decoded)
|
||||
--- * `source-application`: (String or Table, optional): a pattern or list of
|
||||
--- patterns to match against the name of the application from which the URL
|
||||
--- was opened. If this parameter is present, the decoder will only be
|
||||
--- applied when the application matches. Default is to apply the decoder
|
||||
--- regardless of the application.
|
||||
--- If given as strings, `decoder-pattern-or-function` and `pattern-replacement`
|
||||
--- are passed as arguments to
|
||||
--- [string.gsub](https://www.lua.org/manual/5.3/manual.html#pdf-string.gsub)
|
||||
--- applied on the original URL.
|
||||
obj.url_redir_decoders = { }
|
||||
|
||||
--- URLDispatcher.url_patterns
|
||||
--- Variable
|
||||
--- URL dispatch rules.
|
||||
---
|
||||
--- Notes:
|
||||
--- A table containing a list of dispatch rules. Rules are evaluated in the
|
||||
--- order they are declared. Each rule is a table with the following structure:
|
||||
--- `{ url-patterns, app-bundle-ID-or-function, function, app-patterns }`
|
||||
--- * `url-patterns` can be: (a) a single pattern as a string, (b) a table
|
||||
--- containing a list of strings, or (c) a string containing the path of a
|
||||
--- file from which the patterns will be read (if the string contains a valid
|
||||
--- filename it's used as a file, otherwise as a pattern). In case (c), a
|
||||
--- watcher will be set to automatically re-read the contents of the file
|
||||
--- when it changes. If a relative path is given (not starting with a "/"),
|
||||
--- then it is considered to be relative to the Hammerspoon configuration
|
||||
--- directory.
|
||||
--- * If `app-bundle-ID-or-function` is specified as a string, it is
|
||||
--- interpreted as a macOS application ID, and that application will be used
|
||||
--- to open matching URLs. If it is a function pointer, or not given but
|
||||
--- "function" is provided, it is expected to be a function that accepts a
|
||||
--- single argument, and it will be called with the URL.
|
||||
--- * If `app-patterns` is given, it should be a string or a table containing a
|
||||
--- pattern/list of patterns, and the rule will only be evaluated if the URL
|
||||
--- was opened from an application whose name matches one of those patterns.
|
||||
--- * Note that the patterns are [Lua patterns](https://www.lua.org/pil/20.2.html)
|
||||
--- and not regular expressions.
|
||||
--- * Defaults to an empty table, which has the effect of having all URLs
|
||||
--- dispatched to the `default_handler`.
|
||||
obj.url_patterns = { }
|
||||
|
||||
--- URLDispatcher.logger
|
||||
--- Variable
|
||||
--- Logger object used within the Spoon. Can be accessed to set the default log
|
||||
--- level for the messages coming from the Spoon.
|
||||
---
|
||||
--- Notes:
|
||||
--- Example: `spoon.URLDispatcher.logger.setLogLevel("debug")`
|
||||
obj.logger = hs.logger.new('URLDispatcher')
|
||||
|
||||
--- URLDispatcher.set_system_handler
|
||||
--- Variable
|
||||
--- If true, URLDispatcher sets itself as system handler for http requests.
|
||||
--- Defaults to `true`
|
||||
obj.set_system_handler = true
|
||||
|
||||
--- URLDispatcher.pat_files
|
||||
--- Variable
|
||||
--- Internal variable containing a table where the pattern lists read from files are kept indexed by file name, and automatically updated.
|
||||
obj.pat_files = {}
|
||||
|
||||
--- URLDispatcher.pat_watchers
|
||||
--- Variable
|
||||
--- Internal variable containing a table where the watchers for the pattern files are kept indexed by file name.
|
||||
obj.pat_watchers = {}
|
||||
|
||||
-- Local functions to decode URLs
|
||||
function hex_to_char(x)
|
||||
return string.char(tonumber(x, 16))
|
||||
end
|
||||
|
||||
function obj.unescape(url)
|
||||
return url:gsub("%%(%x%x)", hex_to_char)
|
||||
end
|
||||
|
||||
-- Match a single pattern against an application name.
|
||||
function obj.matchapp(app, pat)
|
||||
obj.logger.df("Matching appname '%s' against pattern '%s'", app, pat)
|
||||
return string.find(app, pat)
|
||||
end
|
||||
|
||||
-- Match a pattern or a list of patterns against an application name.
|
||||
-- The pattern can also be nil, in this case it's considered a success.
|
||||
function obj.matchapps(app, pat)
|
||||
local ismatch = (pat == nil) or
|
||||
(type(pat) == 'string' and obj.matchapp(app, pat)) or
|
||||
(type(pat) == 'table' and hs.fnutils.some(pat, hs.fnutils.partial(obj.matchapp, app)))
|
||||
if ismatch then
|
||||
obj.logger.df(" App pattern '%s' is nil or matches application name '%s' - evaluating rule.", pat, app)
|
||||
else
|
||||
obj.logger.df(" App pattern '%s' does not match application name '%s' - skipping rule.", pat, app)
|
||||
end
|
||||
return ismatch
|
||||
end
|
||||
|
||||
function obj:read_and_store(patfile)
|
||||
self.logger.df("Reading patterns from file '%s'", patfile)
|
||||
local pats = {}
|
||||
for line in io.lines(patfile) do
|
||||
-- Skip empty lines and lines starting with "#" (comments)
|
||||
if (line ~= '') and not (string.find(line, '^%s*#')) then
|
||||
table.insert(pats, line)
|
||||
end
|
||||
end
|
||||
self.pat_files[patfile] = hs.fnutils.copy(pats)
|
||||
end
|
||||
|
||||
function obj:patfileWatcher(patfile, paths, flags)
|
||||
-- Only trigger re-reading the file when the 'itemModified' flag is present,
|
||||
-- otherwise the file gets read multiple times due to file manipulations done
|
||||
-- by editors
|
||||
if hs.fnutils.some(flags, function(f) return f['itemModified'] end) then
|
||||
self:read_and_store(patfile)
|
||||
end
|
||||
end
|
||||
|
||||
function obj:setupPatfile(patfile)
|
||||
-- If the file exists, read it and setup a watcher to update it.
|
||||
if hs.fs.attributes(patfile) then
|
||||
self.logger.df("File '%s' has not been loaded, reading it now.", patfile)
|
||||
-- Read the file and set up the watcher to auto-update it.
|
||||
self:read_and_store(patfile)
|
||||
self.logger.df("Creating watcher for file '%s'", patfile)
|
||||
self.pat_watchers[patfile] = hs.pathwatcher.new(patfile, hs.fnutils.partial(self.patfileWatcher, self, patfile)):start()
|
||||
return self.pat_files[patfile]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
--- URLDispatcher:dispatchURL(scheme, host, params, fullUrl, senderPid)
|
||||
--- Method
|
||||
--- Dispatch a URL to an application according to the defined `url_patterns`.
|
||||
---
|
||||
--- Parameters:
|
||||
--- * scheme - A string containing the URL scheme (i.e. "http")
|
||||
--- * host - A string containing the host requested (e.g. "www.hammerspoon.org")
|
||||
--- * params - A table containing the key/value pairs of all the URL parameters
|
||||
--- * fullURL - A string containing the full, original URL. This is the only parameter used in this implementation.
|
||||
--- * senderPID - An integer containing the PID of the application that opened the URL, if available (otherwise -1)
|
||||
---
|
||||
--- Notes:
|
||||
--- * The parameters (follow to the [httpCallback](http://www.hammerspoon.org/docs/hs.urlevent.html#httpCallback) specification)
|
||||
function obj:dispatchURL(scheme, host, params, fullUrl, senderPid)
|
||||
local url = fullUrl
|
||||
local currentApp = ""
|
||||
if senderPid ~= -1 then
|
||||
currentApp = hs.application.applicationForPID(senderPid):name()
|
||||
end
|
||||
self.logger.df("Dispatching URL '%s' from application '%s'", url, currentApp)
|
||||
if self.decode_slack_redir_urls then
|
||||
local newUrl = string.match(url, 'https://slack.redir.net/.*url=(.*)')
|
||||
if newUrl then
|
||||
url = obj.unescape(newUrl)
|
||||
self.logger.df(" Decoded Slack redirect. New URL: '%s'", url)
|
||||
end
|
||||
end
|
||||
for i,dec in ipairs(self.url_redir_decoders) do
|
||||
self.logger.df(" Testing decoder '%s'", dec[1])
|
||||
local processed = false
|
||||
if self.matchapps(currentApp, dec[5]) then
|
||||
if type(dec[2]) == "string" then
|
||||
if string.find(url, dec[2]) then
|
||||
self.logger.df(" Applying pattern-based decoder '%s' to URL '%s'", dec[1], url)
|
||||
url = string.gsub(url, dec[2], dec[3])
|
||||
self.logger.df(" Decoded URL: '%s'", url)
|
||||
processed = true
|
||||
end
|
||||
elseif type(dec[2]) == "function" then
|
||||
self.logger.df(" Applying function-based decoder '%s' to URL '%s'", dec[1], url)
|
||||
url = dec[2](scheme, host, params, fullUrl, senderPid)
|
||||
self.logger.df(" Decoded URL: '%s'", url)
|
||||
processed = true
|
||||
else
|
||||
self.logger.ef(" Decoder '%s' has an unknown second value of type '%s'", dec[1], dec[2])
|
||||
end
|
||||
if processed and (not dec[4]) then
|
||||
self.logger.df(" Unescaping decoded URL '%s'", url)
|
||||
url = obj.unescape(url)
|
||||
self.logger.df(" Unescaped URL: '%s'", url)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
self.logger.df("Final URL to open: '%s'", url)
|
||||
for i,pair in ipairs(self.url_patterns) do
|
||||
self.logger.df("Evaluating rule %s", hs.inspect(pair))
|
||||
|
||||
local pats = pair[1]
|
||||
local app = pair[2]
|
||||
local func = pair[3]
|
||||
local app_pats = pair[4]
|
||||
|
||||
-- If app_pats is given, then first of all check whether the source app
|
||||
-- matches, otherwise we skip the whole thing
|
||||
if self.matchapps(currentApp, app_pats) then
|
||||
-- First determine how to interpret the url-patterns
|
||||
if type(pats) == "string" then
|
||||
-- A string can be a single pattern, or a filename to load
|
||||
if self.pat_files[pats] then
|
||||
-- If it's already a known pattern file, use its content
|
||||
self.logger.df(" File '%s' is already read, using its contents.", pats)
|
||||
pats = self.pat_files[pats]
|
||||
else
|
||||
-- Else, try to load it as a file
|
||||
local patsfile = self:setupPatfile(pats)
|
||||
-- If this fails, we use it as a single pattern
|
||||
if patsfile then
|
||||
pats = patsfile
|
||||
else
|
||||
self.logger.df(" Single pattern given, converting to list for processing.")
|
||||
pats = { pats }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i,p in ipairs(pats) do
|
||||
self.logger.df(" Testing URL with pattern '%s'", p)
|
||||
if string.match(url, p) then
|
||||
local id = nil
|
||||
if type(app) == "string" then
|
||||
id = app
|
||||
elseif type(app) == "function" then
|
||||
func = app
|
||||
end
|
||||
if id ~= nil then
|
||||
self.logger.df(" Match found, opening with '%s'", id)
|
||||
hs.application.launchOrFocusByBundleID(id)
|
||||
hs.urlevent.openURLWithBundle(url, id)
|
||||
return
|
||||
end
|
||||
if func ~= nil then
|
||||
self.logger.df(" Match found, calling func '%s'", func)
|
||||
func(url)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Fall through to the default handler
|
||||
if type(self.default_handler) == "string" then
|
||||
self.logger.df("No match found, opening with default handler '%s'", self.default_handler)
|
||||
hs.application.launchOrFocusByBundleID(self.default_handler)
|
||||
hs.urlevent.openURLWithBundle(url, self.default_handler)
|
||||
elseif type(self.default_handler) == "function" then
|
||||
self.logger.df("No match found, opening with default handler func '%s'", self.default_handler)
|
||||
self.default_handler(url)
|
||||
else
|
||||
self.logger.ef("Unknown type '%s' for default_handler '%s', must be a string or a function.",
|
||||
type(self.default_handler), self.default_handler)
|
||||
end
|
||||
end
|
||||
|
||||
--- URLDispatcher:start()
|
||||
--- Method
|
||||
--- Start dispatching URLs according to the rules
|
||||
---
|
||||
--- Parameters:
|
||||
--- * None
|
||||
function obj:start()
|
||||
if hs.urlevent.httpCallback then
|
||||
self.logger.w("An hs.urlevent.httpCallback was already set. I'm overriding it with my own but you should check if this breaks any other functionality")
|
||||
end
|
||||
hs.urlevent.httpCallback = function(...) self:dispatchURL(...) end
|
||||
if self.set_system_handler then
|
||||
hs.urlevent.setDefaultHandler('http')
|
||||
end
|
||||
-- hs.urlevent.setRestoreHandler('http', self.default_handler)
|
||||
return self
|
||||
end
|
||||
|
||||
return obj
|
||||
91
hammerspoon/app_hider.lua
Normal file
91
hammerspoon/app_hider.lua
Normal file
@@ -0,0 +1,91 @@
|
||||
--- === app_hider ===
|
||||
---
|
||||
--- A Hammerspoon module which hides specified applications when they are
|
||||
--- deactivated (lose focus).
|
||||
|
||||
local obj = {}
|
||||
local autoHideApps = {}
|
||||
|
||||
local function shouldAutoHide(appName)
|
||||
for _, name in ipairs(autoHideApps) do
|
||||
if appName == name then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function appWatcherCallback(appName, eventType, appObject)
|
||||
if eventType == hs.application.watcher.deactivated and shouldAutoHide(appName) then
|
||||
appObject:hide()
|
||||
end
|
||||
end
|
||||
|
||||
local appWatcher = hs.application.watcher.new(appWatcherCallback)
|
||||
obj.started = false
|
||||
|
||||
function obj:start()
|
||||
if obj.started then
|
||||
return
|
||||
end
|
||||
|
||||
appWatcher:start()
|
||||
obj.started = true
|
||||
end
|
||||
|
||||
function obj:stop()
|
||||
if not obj.started then
|
||||
return
|
||||
end
|
||||
|
||||
appWatcher:stop()
|
||||
obj.started = false
|
||||
end
|
||||
|
||||
--- app_hider:autoHide(appName)
|
||||
--- Method
|
||||
--- Adds an application to the auto-hide list.
|
||||
---
|
||||
--- Parameters:
|
||||
--- * appName - A string with the name of the application to auto-hide.
|
||||
function obj:autoHide(appName)
|
||||
if not appName or type(appName) ~= "string" then
|
||||
print("Error: Invalid app name provided to autoHide.")
|
||||
return
|
||||
end
|
||||
|
||||
obj:start() -- Ensure the watcher is running
|
||||
|
||||
-- Prevent duplicates in the autoHideApps table
|
||||
for _, name in ipairs(autoHideApps) do
|
||||
if name == appName then
|
||||
print("App already in auto-hide list: " .. appName)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(autoHideApps, appName)
|
||||
end
|
||||
|
||||
--- app_hider:remove(appName)
|
||||
--- Method
|
||||
--- Removes an application from the auto-hide list.
|
||||
---
|
||||
--- Parameters:
|
||||
--- * appName - A string with the name of the application to remove from the
|
||||
--- auto-hide list.
|
||||
function obj:remove(appName)
|
||||
for i, name in ipairs(autoHideApps) do
|
||||
if name == appName then
|
||||
table.remove(autoHideApps, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- Stop the watcher if the list is empty
|
||||
if #autoHideApps == 0 and obj.started then
|
||||
obj:stop()
|
||||
end
|
||||
end
|
||||
|
||||
return obj
|
||||
@@ -1,38 +1,187 @@
|
||||
-- luacheck: read_globals hs
|
||||
--- === app_toggle ===
|
||||
---
|
||||
--- A Hammerspoon module for toggling between specified applications using
|
||||
--- hotkeys.
|
||||
---
|
||||
--- This module allows you to bind a hotkey to switch focus between specific
|
||||
--- applications and show/hide them.
|
||||
|
||||
local obj = {}
|
||||
|
||||
function obj:bind (mods, key, name, path)
|
||||
hs.hotkey.bind(mods, key, self:toggleFn(name, path))
|
||||
end
|
||||
|
||||
function obj:toggleFn (name, path)
|
||||
return function ()
|
||||
self:toggle(name, path)
|
||||
end
|
||||
end
|
||||
|
||||
function obj:toggle (name, path)
|
||||
local app = self.findRunningApp(name, path)
|
||||
|
||||
if app == nil then
|
||||
return hs.application.open(path or name)
|
||||
end
|
||||
|
||||
if app == hs.application.frontmostApplication() then
|
||||
return app:hide()
|
||||
end
|
||||
|
||||
return app:activate()
|
||||
end
|
||||
|
||||
function obj.findRunningApp (name, path)
|
||||
local function findRunningApp(name, path)
|
||||
for _, app in ipairs(hs.application.runningApplications()) do
|
||||
if app:name() == name and (path == nil or path == app:path()) then
|
||||
-- Get app name, and also get a sanitized version of the name by removing
|
||||
-- any non-printable characters. Some apps like WhatsApp have names that
|
||||
-- contain invisible characters that cause the app to not be found.
|
||||
local appName = app:name()
|
||||
local sanitizedAppName = appName:gsub('[^%g+]', '')
|
||||
|
||||
-- app:path() can error for certain pseudo-apps.
|
||||
-- Guard with pcall and skip on failure to keep iterating.
|
||||
local ok, appPath = pcall(function()
|
||||
return app:path()
|
||||
end)
|
||||
|
||||
-- Skip apps that don't have a path or that don't end with ".app". If the
|
||||
-- path doesn't end with ".app", it's not likely to be a GUI app.
|
||||
if ok and appPath and appPath:match("%.app$")
|
||||
and (appName == name or sanitizedAppName == name)
|
||||
and (path == nil or path == appPath) then
|
||||
return app
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local focusTimes = {}
|
||||
|
||||
local function focusWatcher(_, eventType, appObject)
|
||||
if eventType == hs.application.watcher.activated then
|
||||
focusTimes[appObject:bundleID()] = hs.timer.secondsSinceEpoch()
|
||||
end
|
||||
end
|
||||
|
||||
local appWatcher = hs.application.watcher.new(focusWatcher)
|
||||
obj.started = false
|
||||
|
||||
function obj:start()
|
||||
if obj.started then
|
||||
return
|
||||
end
|
||||
|
||||
appWatcher:start()
|
||||
obj.started = true
|
||||
end
|
||||
|
||||
function obj:stop()
|
||||
if not obj.started then
|
||||
return
|
||||
end
|
||||
|
||||
appWatcher:stop()
|
||||
obj.started = false
|
||||
end
|
||||
|
||||
--- app_toggle:bind(mods, key, ...)
|
||||
--- Method
|
||||
--- Binds a hotkey to toggle between the specified applications.
|
||||
---
|
||||
--- Parameters:
|
||||
--- * mods - A table with the modifiers for the hotkey
|
||||
--- * key - A string with the key for the hotkey
|
||||
--- * ... - A list of tables, each containing an application name and an
|
||||
--- optional path
|
||||
function obj:bind(mods, key, ...)
|
||||
local apps = { ... }
|
||||
if #apps > 1 then
|
||||
self:start()
|
||||
end
|
||||
|
||||
hs.hotkey.bind(mods, key, self:toggleFn(apps))
|
||||
end
|
||||
|
||||
--- app_toggle:toggleFn(apps)
|
||||
--- Method
|
||||
--- Creates and returns a function that toggles between the specified
|
||||
--- applications via app_toggle:toggle() when called.
|
||||
---
|
||||
--- Parameters:
|
||||
--- * apps - A table containing application configurations. Each configuration
|
||||
--- is a table with an application name at the first index and an
|
||||
--- optional path at the second index.
|
||||
---
|
||||
--- Returns:
|
||||
--- * A function that, when called, toggles between the specified applications.
|
||||
---
|
||||
--- Example:
|
||||
--- local toggleApps = obj:toggleFn({{"Firefox"}, {"Safari"}})
|
||||
--- hs.hotkey.bind({"cmd", "ctrl"}, "b", toggleApps)
|
||||
---
|
||||
--- Notes:
|
||||
--- * The returned function can be used as a callback for hotkey bindings or
|
||||
--- other event-driven scenarios.
|
||||
function obj:toggleFn(apps)
|
||||
return function()
|
||||
self:toggle(apps)
|
||||
end
|
||||
end
|
||||
|
||||
--- app_toggle:toggle(apps)
|
||||
--- Method
|
||||
--- Toggles focus/visibility specified applications.
|
||||
---
|
||||
--- Parameters:
|
||||
--- * apps - A table containing application configurations. Each configuration
|
||||
--- is a table with an application name at the first index and an
|
||||
--- optional path at the second index.
|
||||
---
|
||||
--- Notes:
|
||||
--- * If none of the specified applications are running, the function attempts
|
||||
--- to launch the first application in the list.
|
||||
--- * If the most recently focused application in the list is the current
|
||||
--- frontmost application, it will be hidden. Otherwise, the most recently
|
||||
--- focused application will be brought to the front.
|
||||
function obj:toggle(apps)
|
||||
local runningApps = {}
|
||||
local mostRecentApp = nil
|
||||
local mostRecentTime = -1
|
||||
|
||||
for _, appInfo in ipairs(apps) do
|
||||
local name, path = appInfo[1], appInfo[2]
|
||||
local app = findRunningApp(name, path)
|
||||
if app then
|
||||
table.insert(runningApps, app)
|
||||
local focusTime = focusTimes[app:bundleID()] or 0
|
||||
if focusTime > mostRecentTime then
|
||||
mostRecentTime = focusTime
|
||||
mostRecentApp = app
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #runningApps == 0 then
|
||||
local app = apps[1]
|
||||
local status, err = pcall(hs.application.open, app[2] or app[1])
|
||||
if not status then
|
||||
hs.alert.show('Failed to open ' .. (app[2] or app[1]) .. ': ' .. err)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if not mostRecentApp then
|
||||
mostRecentApp = runningApps[1]
|
||||
end
|
||||
|
||||
local frontMostApp = hs.application.frontmostApplication()
|
||||
if frontMostApp and mostRecentApp == frontMostApp then
|
||||
return mostRecentApp:hide()
|
||||
end
|
||||
|
||||
return mostRecentApp:activate()
|
||||
end
|
||||
|
||||
--- app_toggle:showAppInfo()
|
||||
--- Method
|
||||
--- Shows an alert with information about the frontmost application.
|
||||
function obj:showAppInfo()
|
||||
local app = hs.application.frontmostApplication()
|
||||
local ok, appPath = pcall(function()
|
||||
return app:path()
|
||||
end)
|
||||
|
||||
local info = { app:name() .. " (" .. app:bundleID() .. ")" }
|
||||
if ok and appPath then
|
||||
table.insert(info, appPath)
|
||||
else
|
||||
table.insert(info, "Path: <unavailable>")
|
||||
end
|
||||
table.insert(info, "PID: " .. app:pid())
|
||||
|
||||
print("Frontmost app info:")
|
||||
for _, line in ipairs(info) do
|
||||
hs.alert.show(line)
|
||||
print(line)
|
||||
end
|
||||
end
|
||||
|
||||
-- the end
|
||||
return obj
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
local obj = {
|
||||
hostname = nil
|
||||
}
|
||||
|
||||
function obj.getHostname()
|
||||
local f = io.popen ("hostname -s")
|
||||
local hostname = f:read("*a") or ""
|
||||
f:close()
|
||||
hostname = string.gsub(hostname, "\n$", "")
|
||||
return hostname
|
||||
end
|
||||
|
||||
obj.hostname = obj.getHostname()
|
||||
return obj
|
||||
@@ -1,20 +1,19 @@
|
||||
local function require_file(path)
|
||||
local ok, module = pcall(loadfile, path)
|
||||
return (ok and module and module() or nil)
|
||||
end
|
||||
|
||||
local obj = {}
|
||||
|
||||
function obj:init()
|
||||
local env = require('env')
|
||||
local conf_file = "hosts/" .. env.hostname .. ".lua"
|
||||
local conf_req = "hosts." .. env.hostname
|
||||
local hostname = hs.host.localizedName()
|
||||
local conf_file = 'hosts/' .. hostname .. '.lua'
|
||||
local hostmod = require_file(conf_file)
|
||||
|
||||
if self.file_exists(conf_file) then
|
||||
print("loading host config: " .. conf_file)
|
||||
local conf_module = require(conf_req)
|
||||
conf_module:init()
|
||||
if hostmod then
|
||||
print('loading host config: ' .. conf_file)
|
||||
hostmod.init()
|
||||
end
|
||||
end
|
||||
|
||||
function obj.file_exists(name)
|
||||
local f = io.open(name, "r")
|
||||
if f ~= nil then io.close(f) return true else return false end
|
||||
end
|
||||
|
||||
return obj
|
||||
|
||||
74
hammerspoon/hosts/hati.lua
Normal file
74
hammerspoon/hosts/hati.lua
Normal file
@@ -0,0 +1,74 @@
|
||||
local obj = {}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Global Hotkeys
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local apptoggle = require('app_toggle')
|
||||
local apphider = require('app_hider')
|
||||
|
||||
local function init_hotkeys()
|
||||
hs.hotkey.bind({ 'cmd', 'alt', 'ctrl' }, 'S', apptoggle.showAppInfo)
|
||||
|
||||
apptoggle:bind({ 'cmd', 'alt', 'ctrl' }, 'A', { 'Activity Monitor' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, '1', { 'Codex' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, '2', { 'Claude' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, '3', { 'Conductor' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, '4', { 'ChatGPT Atlas' }, { 'ChatGPT' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'A', { 'Argo CD' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'B', { 'TablePlus' }, { 'Lens' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'D', { 'Mail+ for Gmail' }, { 'Notion Mail' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'F', { 'GitButler' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'G', { 'Emacs', '/Applications/Emacs.app' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'T', { 'TeamSpeak 3', '/Applications/TeamSpeak 3 Client.app' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'X', { 'Notion' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'Z', { 'Slack' })
|
||||
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'C',
|
||||
{ 'Notion Calendar' },
|
||||
{ 'Calendar' },
|
||||
{ 'Google Calendar' }
|
||||
)
|
||||
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'E', { 'Cursor' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'W',
|
||||
{ 'Code - Insiders', '/Applications/Visual Studio Code - Insiders.app' },
|
||||
{ 'Code', '/Applications/Visual Studio Code.app' }
|
||||
)
|
||||
|
||||
-- -- Use Ghostty as my primary terminal application.
|
||||
-- apptoggle:bind({ 'cmd', 'ctrl' }, 'R', { 'Ghostty' })
|
||||
-- apphider:autoHide('Ghostty') -- auto-hide Ghostty when it loses focus
|
||||
|
||||
-- -- Use Warp as my primary terminal application.
|
||||
-- apptoggle:bind({ 'cmd', 'ctrl' }, 'R', { 'Warp' })
|
||||
-- apphider:autoHide('Warp') -- auto-hide Warp when it loses focus
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- URL Handling
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- local uh = require('url_handler')
|
||||
|
||||
-- local function init_url_handler()
|
||||
-- uh.default_handler = uh.browsers.arc
|
||||
-- uh.url_patterns = {
|
||||
-- {
|
||||
-- { "%://meet.google.com/" }, uh.browsers.chrome, nil,
|
||||
-- }
|
||||
-- }
|
||||
|
||||
-- uh:init()
|
||||
-- end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Initialization
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function obj.init()
|
||||
init_hotkeys()
|
||||
-- init_url_handler()
|
||||
end
|
||||
|
||||
return obj
|
||||
@@ -1,22 +1,87 @@
|
||||
local obj = {}
|
||||
|
||||
function obj.init()
|
||||
local apptoggle = require('app_toggle')
|
||||
--------------------------------------------------------------------------------
|
||||
-- Global Hotkeys
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
apptoggle:bind({'cmd', 'alt', 'ctrl'}, 'A', 'Activity Monitor')
|
||||
apptoggle:bind({'cmd', 'ctrl'}, '1', 'Microsoft To-Do')
|
||||
apptoggle:bind({'cmd', 'ctrl'}, '4', 'Skitch')
|
||||
apptoggle:bind({'cmd', 'ctrl'}, 'A', 'Messages')
|
||||
apptoggle:bind({'cmd', 'ctrl'}, 'B', 'TablePlus')
|
||||
apptoggle:bind({'cmd', 'ctrl'}, 'C', 'Calendar')
|
||||
apptoggle:bind({'cmd', 'ctrl'}, 'D', 'Mailplane')
|
||||
apptoggle:bind({'cmd', 'ctrl'}, 'E', 'Emacs', '/Applications/Emacs.app')
|
||||
apptoggle:bind({'cmd', 'ctrl'}, 'F', 'Element Nightly')
|
||||
apptoggle:bind({'cmd', 'ctrl'}, 'S', 'Music')
|
||||
apptoggle:bind({'cmd', 'ctrl'}, 'T', 'Discord PTB')
|
||||
apptoggle:bind({'cmd', 'ctrl'}, 'W', 'WhatsApp')
|
||||
apptoggle:bind({'cmd', 'ctrl'}, 'X', 'Notion')
|
||||
apptoggle:bind({'cmd', 'ctrl'}, 'Z', 'Slack')
|
||||
local apptoggle = require('app_toggle')
|
||||
local apphider = require('app_hider')
|
||||
|
||||
local function init_hotkeys()
|
||||
hs.hotkey.bind({ 'cmd', 'alt', 'ctrl' }, 'S', apptoggle.showAppInfo)
|
||||
|
||||
apptoggle:bind({ 'cmd', 'alt', 'ctrl' }, 'A', { 'Activity Monitor' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, '1', { 'Codex' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, '2', { 'Claude' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, '3', { 'Conductor' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, '4', { 'ChatGPT' }, { 'ChatGPT Atlas' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'A', { 'Messages' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'B', { 'TablePlus' }, { 'Sequel Pro' }, { 'Lens' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'D', { 'Mail+ for Gmail' }, { 'Mimestream' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'E', { 'Cursor' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'F', { 'GitButler' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'G', { 'Emacs', '/Applications/Emacs.app' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'T', { 'Discord PTB' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'X', { 'Notion' }, { 'Obsidian' })
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'Z', { 'WhatsApp' })
|
||||
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'W',
|
||||
{ 'Code', '/Applications/Visual Studio Code.app' },
|
||||
{ 'Code - Insiders', '/Applications/Visual Studio Code - Insiders.app' }
|
||||
)
|
||||
|
||||
apptoggle:bind({ 'cmd', 'ctrl' }, 'C',
|
||||
{ 'Calendar' },
|
||||
{ 'Google Calendar' },
|
||||
{ 'Notion Calendar' }
|
||||
)
|
||||
|
||||
-- -- Use Warp as my primary terminal application.
|
||||
-- apptoggle:bind({ 'cmd', 'ctrl' }, 'R', { 'Warp' })
|
||||
-- apphider:autoHide('Warp') -- auto-hide Warp when it loses focus
|
||||
|
||||
-- Use Ghostty as my primary terminal application.
|
||||
-- apptoggle:bind({ 'cmd', 'ctrl' }, 'R', { 'Ghostty' })
|
||||
-- apphider:autoHide('Ghostty') -- auto-hide Ghostty when it loses focus
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- URL Handling
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- local uh = require('url_handler')
|
||||
|
||||
-- local function init_url_handler()
|
||||
-- uh.default_handler = uh.browsers.arc
|
||||
-- uh.url_patterns = {
|
||||
-- {
|
||||
-- { "%://meet.google.com/" }, uh.browsers.chrome, nil,
|
||||
-- }
|
||||
-- }
|
||||
-- -- uh.url_redir_decoders = {
|
||||
-- -- {
|
||||
-- -- "MS Teams links",
|
||||
-- -- function(_, _, params, fullUrl)
|
||||
-- -- if params.url then
|
||||
-- -- return params.url
|
||||
-- -- else
|
||||
-- -- return fullUrl
|
||||
-- -- end
|
||||
-- -- end,
|
||||
-- -- nil, true, "Microsoft Teams"
|
||||
-- -- },
|
||||
-- -- }
|
||||
|
||||
-- uh:init()
|
||||
-- end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Initialization
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function obj.init()
|
||||
init_hotkeys()
|
||||
-- init_url_handler()
|
||||
end
|
||||
|
||||
return obj
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
-- luacheck: read_globals hs spoon
|
||||
|
||||
-- Reload config hotkey
|
||||
hs.hotkey.bind({'cmd', 'alt', 'ctrl'}, 'R', hs.reload)
|
||||
hs.hotkey.bind({'cmd', 'alt', 'ctrl'}, 'C', hs.toggleConsole)
|
||||
hs.hotkey.bind({ 'cmd', 'alt', 'ctrl' }, 'R', hs.reload)
|
||||
hs.hotkey.bind({ 'cmd', 'alt', 'ctrl' }, 'C', hs.toggleConsole)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Set Hammerspoon options
|
||||
@@ -21,6 +21,7 @@ hs.console.behaviorAsLabels { 'moveToActiveSpace' }
|
||||
|
||||
-- Draw pretty rounded corners on all screens.
|
||||
hs.loadSpoon('RoundedCorners')
|
||||
spoon.RoundedCorners.radius = 12
|
||||
spoon.RoundedCorners:start()
|
||||
|
||||
-- Automatically pause music when headphones are unplugged.
|
||||
@@ -42,6 +43,13 @@ hostconfig:init()
|
||||
local wm = require('window_management')
|
||||
wm:init()
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Misc. Helpers
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local kd = require('kill_dock')
|
||||
hs.hotkey.bind({ 'cmd', 'alt', 'ctrl' }, 'D', kd.killDock)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- The End
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
18
hammerspoon/kill_dock.lua
Normal file
18
hammerspoon/kill_dock.lua
Normal file
@@ -0,0 +1,18 @@
|
||||
-- luacheck: read_globals hs
|
||||
|
||||
--- === kill_dock ===
|
||||
---
|
||||
--- Function to kill the Dock.
|
||||
|
||||
local obj = {}
|
||||
|
||||
--- kill_dock.killDock()
|
||||
--- Function
|
||||
--- Kills the Dock by executing `killall Dock`.
|
||||
function obj.killDock()
|
||||
hs.alert.show('Restarting Dock...')
|
||||
hs.execute("killall Dock", true)
|
||||
end
|
||||
|
||||
-- the end
|
||||
return obj
|
||||
143
hammerspoon/url_handler.lua
Normal file
143
hammerspoon/url_handler.lua
Normal file
@@ -0,0 +1,143 @@
|
||||
-- luacheck: read_globals hs
|
||||
|
||||
--- === url_handler ===
|
||||
---
|
||||
--- URL handler for Hammerspoon. This module wraps the URLDispatcher spoon with
|
||||
--- a number of extra helper function to make it easier to configure.
|
||||
---
|
||||
--- You will need to separately install the URLDispatcher spoon for this module
|
||||
--- to work.
|
||||
|
||||
hs.loadSpoon('URLDispatcher')
|
||||
local obj = {
|
||||
_url_dispatcher = spoon.URLDispatcher
|
||||
|
||||
}
|
||||
|
||||
--- url_handler.default_handler
|
||||
--- Variable
|
||||
--- The default handler for URLs that don't match any of the patterns. If this
|
||||
--- is not nil, it will be set as default_handler on the URLDispatcher spoon.
|
||||
obj.default_handler = nil
|
||||
|
||||
--- url_handler.decode_slack_redir_urls
|
||||
--- Variable
|
||||
--- A boolean indicating whether to decode Slack redirect URLs. If this is not
|
||||
--- nil, it will be set as decode_slack_redir_urls on the URLDispatcher spoon.
|
||||
obj.decode_slack_redir_urls = nil
|
||||
|
||||
--- url_handler.url_patterns
|
||||
--- Variable
|
||||
--- A table of URL patterns to match against. If this is not nil, it will be set
|
||||
--- as url_patterns on the URLDispatcher spoon.
|
||||
obj.url_patterns = nil
|
||||
|
||||
--- url_handler.url_redir_decoders
|
||||
--- Variable
|
||||
--- A table of URL redirect decoders. If this is not nil, it will be set as
|
||||
--- url_redir_decoders on the URLDispatcher spoon.
|
||||
obj.url_redir_decoders = nil
|
||||
|
||||
--- url_handler.browsers
|
||||
--- Variable
|
||||
--- A table of browser names and corresponding bundle IDs that can be used in
|
||||
--- the url_patterns table.
|
||||
obj.browsers = {
|
||||
arc = 'company.thebrowser.Browser',
|
||||
brave = 'com.brave.Browser',
|
||||
camino = 'org.mozilla.camino',
|
||||
chrome = 'com.google.Chrome',
|
||||
chromium = 'org.chromium.Chromium',
|
||||
edge = 'com.microsoft.edgemac',
|
||||
firefox = 'org.mozilla.firefox',
|
||||
flock = 'com.flock.Flock',
|
||||
icab = 'de.icab.iCab',
|
||||
maxthon = 'com.maxthon.Maxthon',
|
||||
omniweb = 'com.omnigroup.OmniWeb5',
|
||||
opera = 'com.operasoftware.Opera',
|
||||
orion = 'com.orionbrowser.orion',
|
||||
palemoon = 'com.palemoon.palemoon',
|
||||
safari = 'com.apple.Safari',
|
||||
seamonkey = 'org.mozilla.seamonkey',
|
||||
sigmaos = 'com.sigmaos.sigmaos.macos',
|
||||
tor = 'org.mozilla.tor browser',
|
||||
vivaldi = 'com.vivaldi.Vivaldi',
|
||||
waterfox = 'net.waterfox.waterfox',
|
||||
yandex = 'ru.yandex.desktop.yandex-browser',
|
||||
}
|
||||
|
||||
--- url_handler.open(appID, url)
|
||||
--- Function
|
||||
--- Open url with the specified application bundle ID. This is a helper function
|
||||
--- that's useful if you need to build custom functions to open URLs.
|
||||
function obj.open(url, appID)
|
||||
hs.application.launchOrFocusByBundleID(appID)
|
||||
hs.urlevent.openURLWithBundle(url, appID)
|
||||
end
|
||||
|
||||
--- url_handler.appID(appPath)
|
||||
--- Function
|
||||
--- Returns the bundle ID for the specified application path.
|
||||
function obj.appID(appPath)
|
||||
local info = hs.application.infoForBundlePath(appPath)
|
||||
if info then
|
||||
return info['CFBundleIdentifier']
|
||||
end
|
||||
end
|
||||
|
||||
function obj._chromiumProfile(app, profile)
|
||||
return function(url)
|
||||
hs.task.new("/usr/bin/open", nil, {
|
||||
"-n",
|
||||
"-a", app,
|
||||
"--args",
|
||||
"--profile-directory=" .. profile,
|
||||
url
|
||||
}):start()
|
||||
end
|
||||
end
|
||||
|
||||
--- url_handler.chromeProfile(profile)
|
||||
--- Function
|
||||
--- Returns a function that opens the specified URL in Google Chrome using the
|
||||
--- given profile.
|
||||
---
|
||||
--- This assumes that Microsoft Edge is already installed and available to use.
|
||||
function obj.chromeProfile(profile)
|
||||
return obj._chromiumProfile("Google Chrome", profile)
|
||||
end
|
||||
|
||||
--- url_handler.edgeProfile(profile)
|
||||
--- Function
|
||||
--- Returns a function that opens the specified URL in Microsoft Edge using the
|
||||
--- given profile.
|
||||
---
|
||||
--- This assumes that Microsoft Edge is already installed and available to use.
|
||||
function obj.edgeProfile(profile)
|
||||
return obj._chromiumProfile("Microsoft Edge", profile)
|
||||
end
|
||||
|
||||
--- url_handler.init()
|
||||
--- Function
|
||||
--- Initialize URL handler. This will set the default_handler, url_patterns,
|
||||
--- and url_redir_decoders on the URLDispatcher spoon, followed by calling its
|
||||
--- start() method.
|
||||
function obj:init()
|
||||
local keys = {
|
||||
"default_handler",
|
||||
"decode_slack_redir_urls",
|
||||
"url_patterns",
|
||||
"url_redir_decoders"
|
||||
}
|
||||
|
||||
for _, key in ipairs(keys) do
|
||||
if self[key] ~= nil then
|
||||
self._url_dispatcher[key] = self[key]
|
||||
end
|
||||
end
|
||||
|
||||
self._url_dispatcher:start()
|
||||
end
|
||||
|
||||
-- the end
|
||||
return obj
|
||||
@@ -1,33 +1,37 @@
|
||||
-- luacheck: read_globals hs
|
||||
|
||||
local mouse = require('hs.mouse')
|
||||
local eventtap = require('hs.eventtap')
|
||||
local grid = require('hs.grid')
|
||||
local hotkey = require('hs.hotkey')
|
||||
local mouse = require('hs.mouse')
|
||||
local timer = require('hs.timer')
|
||||
local window = require('hs.window')
|
||||
|
||||
-- configuration
|
||||
-- Configuration
|
||||
local wm = {
|
||||
animationDuration = 0.0,
|
||||
gridSizes = { default = '30x20', interactive = '8x4' },
|
||||
gridTextSize = 50,
|
||||
margins = { w = 4, h = 4 }
|
||||
margins = { w = 0, h = 0 }
|
||||
}
|
||||
|
||||
-- initialize and register keybindings
|
||||
function wm:init ()
|
||||
-- Initialize and register keybindings
|
||||
function wm:init()
|
||||
-- setup
|
||||
local bind = require('hs.hotkey').bind
|
||||
local bindAndRepeat = self.bindAndRepeat
|
||||
|
||||
hs.window.animationDuration = self.animationDuration
|
||||
window.animationDuration = self.animationDuration
|
||||
grid.setGrid(self.gridSizes.default)
|
||||
grid.setMargins(self.margins)
|
||||
grid.ui.textSize = self.gridTextSize
|
||||
|
||||
--
|
||||
-- move and resize to preset grid locations
|
||||
-- Move and resize to preset grid locations
|
||||
--
|
||||
|
||||
-- show interactive grid menu
|
||||
bind({'cmd', 'ctrl'}, '2',
|
||||
-- Show interactive grid menu
|
||||
bind({ 'cmd', 'ctrl' }, '§',
|
||||
function()
|
||||
grid.setGrid(self.gridSizes.interactive)
|
||||
grid.show(
|
||||
@@ -38,145 +42,148 @@ function wm:init ()
|
||||
end
|
||||
)
|
||||
|
||||
-- left half
|
||||
bind({'cmd', 'ctrl'}, 'J', self.adjustWindow(0, 0, 15, 20))
|
||||
-- right half
|
||||
bind({'cmd', 'ctrl'}, 'L', self.adjustWindow(15, 0, 15, 20))
|
||||
-- top half
|
||||
bind({'cmd', 'ctrl'}, 'I', self.adjustWindow(0, 0, 30, 10))
|
||||
-- bottom half
|
||||
bind({'cmd', 'ctrl'}, 'K', self.adjustWindow(0, 10, 30, 10))
|
||||
-- Left half
|
||||
bind({ 'cmd', 'ctrl' }, 'J', self.adjustWindow(0, 0, 15, 20))
|
||||
-- Right half
|
||||
bind({ 'cmd', 'ctrl' }, 'L', self.adjustWindow(15, 0, 15, 20))
|
||||
-- Top half
|
||||
bind({ 'cmd', 'ctrl' }, 'I', self.adjustWindow(0, 0, 30, 10))
|
||||
-- Bottom half
|
||||
bind({ 'cmd', 'ctrl' }, 'K', self.adjustWindow(0, 10, 30, 10))
|
||||
|
||||
-- left narrow
|
||||
bind({'ctrl', 'alt'}, 'U', self.adjustWindow(0, 0, 12, 20))
|
||||
-- right narrow
|
||||
bind({'ctrl', 'alt'}, 'O', self.adjustWindow(18, 0, 12, 20))
|
||||
-- Left narrow
|
||||
bind({ 'ctrl', 'alt' }, 'U', self.adjustWindow(0, 0, 12, 20))
|
||||
-- Left super narrow
|
||||
bind({ 'cmd', 'ctrl', 'alt' }, 'U', self.adjustWindow(0, 0, 9, 20))
|
||||
-- Right narrow
|
||||
bind({ 'ctrl', 'alt' }, 'O', self.adjustWindow(18, 0, 12, 20))
|
||||
-- Right super narrow
|
||||
bind({ 'cmd', 'ctrl', 'alt' }, 'O', self.adjustWindow(21, 0, 9, 20))
|
||||
|
||||
-- left wide
|
||||
bind({'cmd', 'ctrl'}, 'U', self.adjustWindow(0, 0, 18, 20))
|
||||
-- right wide
|
||||
bind({'cmd', 'ctrl'}, 'O', self.adjustWindow(12, 0, 18, 20))
|
||||
-- Left wide
|
||||
bind({ 'cmd', 'ctrl' }, 'U', self.adjustWindow(0, 0, 18, 20))
|
||||
-- Right wide
|
||||
bind({ 'cmd', 'ctrl' }, 'O', self.adjustWindow(12, 0, 18, 20))
|
||||
|
||||
-- center super narrow
|
||||
bind({'cmd', 'ctrl', 'alt'}, '\\', self.adjustWindow(10, 0, 10, 20))
|
||||
-- center narrow small
|
||||
bind({'ctrl', 'alt'}, '\\', self.adjustWindow(9, 0, 12, 20))
|
||||
-- center narrow
|
||||
bind({'cmd', 'ctrl'}, '\\', self.adjustWindow(7, 0, 16, 20))
|
||||
-- Center super narrow
|
||||
bind({ 'cmd', 'ctrl', 'alt' }, '\\', self.adjustWindow(10, 0, 10, 20))
|
||||
-- Center narrow small
|
||||
bind({ 'ctrl', 'alt' }, '\\', self.adjustWindow(9, 0, 12, 20))
|
||||
-- Center narrow
|
||||
bind({ 'cmd', 'ctrl' }, '\\', self.adjustWindow(7, 0, 16, 20))
|
||||
|
||||
-- center medium small
|
||||
bind({'ctrl', 'alt'}, '\'', self.adjustWindow(6, 0, 18, 20))
|
||||
-- center medium
|
||||
bind({'cmd', 'ctrl'}, '\'', self.adjustWindow(5, 0, 20, 20))
|
||||
-- Center medium small
|
||||
bind({ 'ctrl', 'alt' }, '\'', self.adjustWindow(6, 0, 18, 20))
|
||||
-- Center medium
|
||||
bind({ 'cmd', 'ctrl' }, '\'', self.adjustWindow(5, 0, 20, 20))
|
||||
|
||||
-- center wide small
|
||||
bind({'ctrl', 'alt'}, ';', self.adjustWindow(4, 0, 22, 20))
|
||||
-- center wide
|
||||
bind({'cmd', 'ctrl'}, ';', self.adjustWindow(3, 0, 24, 20))
|
||||
-- Center wide small
|
||||
bind({ 'ctrl', 'alt' }, ';', self.adjustWindow(4, 0, 22, 20))
|
||||
-- Center wide
|
||||
bind({ 'cmd', 'ctrl' }, ';', self.adjustWindow(3, 0, 24, 20))
|
||||
|
||||
-- maximized
|
||||
bind({'cmd', 'ctrl'}, 'H', grid.maximizeWindow)
|
||||
-- Maximized
|
||||
bind({ 'cmd', 'ctrl' }, 'H', grid.maximizeWindow)
|
||||
|
||||
|
||||
--
|
||||
-- move and resize windows
|
||||
-- Move and resize windows
|
||||
--
|
||||
|
||||
bind({'cmd', 'ctrl', 'alt'}, 'F', self.resizeWindow(770, 634))
|
||||
bind({'cmd', 'ctrl', 'alt'}, 'X', self.adjustWindow(0, 3, 10, 14))
|
||||
bind({ 'cmd', 'ctrl', 'alt' }, 'F', self.resizeWindow(900, 642))
|
||||
bind({ 'cmd', 'ctrl', 'alt' }, 'X', self.adjustWindow(0, 3, 10, 14))
|
||||
|
||||
-- resize windows
|
||||
bindAndRepeat({'cmd', 'ctrl', 'alt'}, 'J', self.resizeWindowOnGrid(-1, 0))
|
||||
bindAndRepeat({'cmd', 'ctrl', 'alt'}, 'L', self.resizeWindowOnGrid(1, 0))
|
||||
bindAndRepeat({'cmd', 'ctrl', 'alt'}, 'I', self.resizeWindowOnGrid(0, -1))
|
||||
bindAndRepeat({'cmd', 'ctrl', 'alt'}, 'K', self.resizeWindowOnGrid(0, 1))
|
||||
-- Resize windows
|
||||
bindAndRepeat({ 'cmd', 'ctrl', 'alt' }, 'J', self.resizeWindowOnGrid(-1, 0))
|
||||
bindAndRepeat({ 'cmd', 'ctrl', 'alt' }, 'L', self.resizeWindowOnGrid(1, 0))
|
||||
bindAndRepeat({ 'cmd', 'ctrl', 'alt' }, 'I', self.resizeWindowOnGrid(0, -1))
|
||||
bindAndRepeat({ 'cmd', 'ctrl', 'alt' }, 'K', self.resizeWindowOnGrid(0, 1))
|
||||
|
||||
-- move window relative
|
||||
bindAndRepeat({'ctrl', 'alt'}, 'J', self.moveWindowOnGrid(-1, 0))
|
||||
bindAndRepeat({'ctrl', 'alt'}, 'L', self.moveWindowOnGrid(1, 0))
|
||||
bindAndRepeat({'ctrl', 'alt'}, 'I', self.moveWindowOnGrid(0, -1))
|
||||
bindAndRepeat({'ctrl', 'alt'}, 'K', self.moveWindowOnGrid(0, 1))
|
||||
-- Move window relative
|
||||
bindAndRepeat({ 'ctrl', 'alt' }, 'J', self.moveWindowOnGrid(-1, 0))
|
||||
bindAndRepeat({ 'ctrl', 'alt' }, 'L', self.moveWindowOnGrid(1, 0))
|
||||
bindAndRepeat({ 'ctrl', 'alt' }, 'I', self.moveWindowOnGrid(0, -1))
|
||||
bindAndRepeat({ 'ctrl', 'alt' }, 'K', self.moveWindowOnGrid(0, 1))
|
||||
|
||||
-- enlarge horizontally
|
||||
bindAndRepeat({'cmd', 'ctrl', 'shift'}, '\\',
|
||||
-- Enlarge horizontally
|
||||
bindAndRepeat({ 'cmd', 'ctrl', 'shift' }, '\\',
|
||||
self.resizeWindowOnGridSymmetrically(1, 0))
|
||||
-- shrink horizontally
|
||||
bindAndRepeat({'cmd', 'ctrl', 'shift'}, '\'',
|
||||
-- Shrink horizontally
|
||||
bindAndRepeat({ 'cmd', 'ctrl', 'shift' }, '\'',
|
||||
self.resizeWindowOnGridSymmetrically(-1, 0))
|
||||
|
||||
|
||||
--
|
||||
-- move windows between spaces
|
||||
-- Move windows between spaces
|
||||
--
|
||||
|
||||
bind({'ctrl', 'alt'}, 'left', self.moveWindowToSpace('left'))
|
||||
bind({'ctrl', 'alt'}, 'right', self.moveWindowToSpace('right'))
|
||||
bind({'ctrl', 'alt'}, '1', self.moveWindowToSpace('1'))
|
||||
bind({'ctrl', 'alt'}, '2', self.moveWindowToSpace('2'))
|
||||
bind({'ctrl', 'alt'}, '3', self.moveWindowToSpace('3'))
|
||||
bind({'ctrl', 'alt'}, '4', self.moveWindowToSpace('4'))
|
||||
bind({'ctrl', 'alt'}, '5', self.moveWindowToSpace('5'))
|
||||
bind({'ctrl', 'alt'}, '6', self.moveWindowToSpace('6'))
|
||||
bind({'ctrl', 'alt'}, '7', self.moveWindowToSpace('7'))
|
||||
bind({'ctrl', 'alt'}, '8', self.moveWindowToSpace('8'))
|
||||
bind({'ctrl', 'alt'}, '9', self.moveWindowToSpace('9'))
|
||||
bind({'ctrl', 'alt'}, '0', self.moveWindowToSpace('0'))
|
||||
bind({ 'ctrl', 'alt' }, 'left', self.moveWindowToSpace('left'))
|
||||
bind({ 'ctrl', 'alt' }, 'right', self.moveWindowToSpace('right'))
|
||||
bind({ 'ctrl', 'alt' }, '1', self.moveWindowToSpace('1'))
|
||||
bind({ 'ctrl', 'alt' }, '2', self.moveWindowToSpace('2'))
|
||||
bind({ 'ctrl', 'alt' }, '3', self.moveWindowToSpace('3'))
|
||||
bind({ 'ctrl', 'alt' }, '4', self.moveWindowToSpace('4'))
|
||||
bind({ 'ctrl', 'alt' }, '5', self.moveWindowToSpace('5'))
|
||||
bind({ 'ctrl', 'alt' }, '6', self.moveWindowToSpace('6'))
|
||||
bind({ 'ctrl', 'alt' }, '7', self.moveWindowToSpace('7'))
|
||||
bind({ 'ctrl', 'alt' }, '8', self.moveWindowToSpace('8'))
|
||||
bind({ 'ctrl', 'alt' }, '9', self.moveWindowToSpace('9'))
|
||||
bind({ 'ctrl', 'alt' }, '0', self.moveWindowToSpace('0'))
|
||||
|
||||
|
||||
--
|
||||
-- move windows between displays
|
||||
-- Move windows between displays
|
||||
--
|
||||
|
||||
-- move to screen to the left
|
||||
bind({'cmd', 'ctrl'}, ',',
|
||||
function ()
|
||||
local win = hs.window.focusedWindow()
|
||||
-- Move to screen to the left
|
||||
bind({ 'cmd', 'ctrl' }, ',',
|
||||
function()
|
||||
local win = window.focusedWindow()
|
||||
win:moveOneScreenWest()
|
||||
grid.snap(win)
|
||||
end
|
||||
)
|
||||
|
||||
-- move to screen to the right
|
||||
bind({'cmd', 'ctrl'}, '.',
|
||||
function ()
|
||||
local win = hs.window.focusedWindow()
|
||||
-- Move to screen to the right
|
||||
bind({ 'cmd', 'ctrl' }, '.',
|
||||
function()
|
||||
local win = window.focusedWindow()
|
||||
win:moveOneScreenEast()
|
||||
grid.snap(win)
|
||||
end
|
||||
)
|
||||
|
||||
-- move to screen above
|
||||
bind({'cmd', 'ctrl', 'alt'}, '.',
|
||||
function ()
|
||||
local win = hs.window.focusedWindow()
|
||||
-- Move to screen above
|
||||
bind({ 'cmd', 'ctrl', 'alt' }, '.',
|
||||
function()
|
||||
local win = window.focusedWindow()
|
||||
win:moveOneScreenNorth()
|
||||
grid.snap(win)
|
||||
end
|
||||
)
|
||||
|
||||
-- move to screen bellow
|
||||
bind({'cmd', 'ctrl', 'alt'}, ',',
|
||||
function ()
|
||||
local win = hs.window.focusedWindow()
|
||||
-- Move to screen below
|
||||
bind({ 'cmd', 'ctrl', 'alt' }, ',',
|
||||
function()
|
||||
local win = window.focusedWindow()
|
||||
win:moveOneScreenSouth()
|
||||
grid.snap(win)
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- private methods
|
||||
-- Private methods
|
||||
--
|
||||
|
||||
wm.bindAndRepeat = function (mod, key, fn)
|
||||
hs.hotkey.bind(mod, key, fn, nil, fn)
|
||||
wm.bindAndRepeat = function(mod, key, fn)
|
||||
hotkey.bind(mod, key, fn, nil, fn)
|
||||
end
|
||||
|
||||
wm.adjustWindow = function (x, y, w, h)
|
||||
return function ()
|
||||
wm.adjustWindow = function(x, y, w, h)
|
||||
return function()
|
||||
grid.adjustWindow(
|
||||
function (cell)
|
||||
function(cell)
|
||||
cell.x = x
|
||||
cell.y = y
|
||||
cell.w = w
|
||||
@@ -186,9 +193,9 @@ wm.adjustWindow = function (x, y, w, h)
|
||||
end
|
||||
end
|
||||
|
||||
wm.resizeWindow = function (w, h)
|
||||
return function ()
|
||||
local win = hs.window.focusedWindow()
|
||||
wm.resizeWindow = function(w, h)
|
||||
return function()
|
||||
local win = window.focusedWindow()
|
||||
local f = win:frame()
|
||||
|
||||
f.w = w
|
||||
@@ -198,8 +205,8 @@ wm.resizeWindow = function (w, h)
|
||||
end
|
||||
|
||||
wm.moveWindow = function(x, y)
|
||||
return function ()
|
||||
local win = hs.window.focusedWindow()
|
||||
return function()
|
||||
local win = window.focusedWindow()
|
||||
local f = win:frame()
|
||||
|
||||
f.x = x
|
||||
@@ -208,9 +215,9 @@ wm.moveWindow = function(x, y)
|
||||
end
|
||||
end
|
||||
|
||||
wm.moveWindowRelative = function (x, y)
|
||||
return function ()
|
||||
local win = hs.window.focusedWindow()
|
||||
wm.moveWindowRelative = function(x, y)
|
||||
return function()
|
||||
local win = window.focusedWindow()
|
||||
local f = win:frame()
|
||||
|
||||
f.x = f.x + x
|
||||
@@ -219,10 +226,10 @@ wm.moveWindowRelative = function (x, y)
|
||||
end
|
||||
end
|
||||
|
||||
wm.moveWindowOnGrid = function (x, y)
|
||||
return function ()
|
||||
wm.moveWindowOnGrid = function(x, y)
|
||||
return function()
|
||||
grid.adjustWindow(
|
||||
function (cell)
|
||||
function(cell)
|
||||
local max = grid.getGrid()
|
||||
|
||||
if ((cell.x + x) + cell.w) <= max.w then
|
||||
@@ -237,10 +244,10 @@ wm.moveWindowOnGrid = function (x, y)
|
||||
end
|
||||
end
|
||||
|
||||
wm.resizeWindowOnGrid = function (w, h)
|
||||
return function ()
|
||||
wm.resizeWindowOnGrid = function(w, h)
|
||||
return function()
|
||||
grid.adjustWindow(
|
||||
function (cell)
|
||||
function(cell)
|
||||
local max = grid.getGrid()
|
||||
|
||||
if cell.x == 0 and cell.w == max.w then
|
||||
@@ -281,10 +288,10 @@ wm.resizeWindowOnGrid = function (w, h)
|
||||
end
|
||||
end
|
||||
|
||||
wm.resizeWindowOnGridSymmetrically = function (w, h)
|
||||
return function ()
|
||||
wm.resizeWindowOnGridSymmetrically = function(w, h)
|
||||
return function()
|
||||
grid.adjustWindow(
|
||||
function (cell)
|
||||
function(cell)
|
||||
local max = grid.getGrid()
|
||||
|
||||
if w ~= 0 and cell.w + (w * 2) >= 2 then
|
||||
@@ -316,45 +323,43 @@ end
|
||||
-- Requires ctrl+<left>/<right> and ctrl+<num> system keybindings, originally
|
||||
-- from:
|
||||
-- https://github.com/Hammerspoon/hammerspoon/issues/235#issuecomment-101069303
|
||||
wm.moveWindowToSpace = function (direction)
|
||||
wm.moveWindowToSpace = function(direction)
|
||||
return function()
|
||||
local mouseOrigin = mouse.absolutePosition()
|
||||
local win = hs.window.focusedWindow()
|
||||
local app = win:application()
|
||||
local win = window.focusedWindow()
|
||||
local clickPoint = win:zoomButtonRect()
|
||||
|
||||
-- click and hold next to the zoom button close to the top of the window
|
||||
clickPoint.x = clickPoint.x + clickPoint.w + 5
|
||||
clickPoint.x = clickPoint.x + clickPoint.w + 2
|
||||
clickPoint.y = win:frame().y + 7
|
||||
|
||||
local mouseClickEvent = hs.eventtap.event.newMouseEvent(
|
||||
hs.eventtap.event.types.leftMouseDown, clickPoint
|
||||
local mouseClickEvent = eventtap.event.newMouseEvent(
|
||||
eventtap.event.types.leftMouseDown, clickPoint
|
||||
)
|
||||
mouseClickEvent:post()
|
||||
hs.timer.usleep(150000)
|
||||
timer.usleep(150000)
|
||||
|
||||
local nextSpaceDownEvent = hs.eventtap.event.newKeyEvent(
|
||||
{"ctrl"}, direction, true
|
||||
local nextSpaceDownEvent = eventtap.event.newKeyEvent(
|
||||
{ "ctrl" }, direction, true
|
||||
)
|
||||
nextSpaceDownEvent:post()
|
||||
hs.timer.usleep(150000)
|
||||
timer.usleep(150000)
|
||||
|
||||
local nextSpaceUpEvent = hs.eventtap.event.newKeyEvent(
|
||||
{"ctrl"}, direction, false
|
||||
local nextSpaceUpEvent = eventtap.event.newKeyEvent(
|
||||
{ "ctrl" }, direction, false
|
||||
)
|
||||
nextSpaceUpEvent:post()
|
||||
hs.timer.usleep(150000)
|
||||
timer.usleep(150000)
|
||||
|
||||
local mouseReleaseEvent = hs.eventtap.event.newMouseEvent(
|
||||
hs.eventtap.event.types.leftMouseUp, clickPoint
|
||||
local mouseReleaseEvent = eventtap.event.newMouseEvent(
|
||||
eventtap.event.types.leftMouseUp, clickPoint
|
||||
)
|
||||
mouseReleaseEvent:post()
|
||||
hs.timer.usleep(150000)
|
||||
timer.usleep(150000)
|
||||
|
||||
mouse.setAbsolutePosition(mouseOrigin)
|
||||
mouse.absolutePosition(mouseOrigin)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- the end
|
||||
return wm
|
||||
|
||||
37
install.sh
37
install.sh
@@ -11,30 +11,41 @@ PRIVATE_PATH="private"
|
||||
SYMLINKS=(
|
||||
Brewfile
|
||||
ackrc
|
||||
alacritty.yml
|
||||
alacritty.toml
|
||||
bitbar
|
||||
coffeelint.json
|
||||
config/kitty/kitty.conf
|
||||
config/ghostty
|
||||
config/kitty
|
||||
config/mise/config.toml
|
||||
config/mise/settings.toml
|
||||
config/nix/nix.conf
|
||||
config/solargraph/config.yml
|
||||
config/starship.toml
|
||||
config/tlrc/config.toml
|
||||
config/xkeysnail/config.py
|
||||
config/k9s
|
||||
erlang
|
||||
eslintrc.js
|
||||
gemrc
|
||||
gitattributes
|
||||
gitconfig
|
||||
gitignore
|
||||
hammerspoon
|
||||
hgrc
|
||||
hyper.js
|
||||
irbrc
|
||||
logrotate.d
|
||||
markdownlint.yaml
|
||||
peco
|
||||
powconfig
|
||||
prettierrc.js
|
||||
pryrc
|
||||
reek.yml
|
||||
rspec
|
||||
rubocop.yml
|
||||
rustfmt.toml
|
||||
tmux
|
||||
tmux.conf
|
||||
warp
|
||||
zprofile
|
||||
zshenv
|
||||
zshrc
|
||||
)
|
||||
@@ -76,6 +87,11 @@ install_private() {
|
||||
"$ROOT_PATH/$PRIVATE_PATH"
|
||||
}
|
||||
|
||||
install_agentic() {
|
||||
git_clone "git@github.com:jimeh/agentic.git" \
|
||||
"$HOME/.config/agentic"
|
||||
}
|
||||
|
||||
install_launch_agents() {
|
||||
mkdir -p "$HOME/Library/LaunchAgents"
|
||||
for file in $ROOT_PATH/launch_agents/*.plist; do
|
||||
@@ -117,6 +133,10 @@ install_emacs_config() {
|
||||
git_clone 'git@github.com:jimeh/.emacs.d.git' "$TARGET/.config/emacs-siren"
|
||||
}
|
||||
|
||||
install_rustup() {
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
}
|
||||
|
||||
#
|
||||
# Helper functions
|
||||
#
|
||||
@@ -207,6 +227,7 @@ dot_symlink() {
|
||||
done
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$target")"
|
||||
symlink "$source" "$target"
|
||||
}
|
||||
|
||||
@@ -240,9 +261,11 @@ display_help() {
|
||||
echo ' info: Display target and source directory information.'
|
||||
echo ' emacs_config: Install Emacs configuration.'
|
||||
echo ' private: Install private dotfiles.'
|
||||
echo ' agentic: Clone agentic repo to ~/.config/agentic.'
|
||||
echo ' homebrew: Install Homebrew (Mac OS X only).'
|
||||
echo ' rbenv: Install rbenv, a Ruby version manager.'
|
||||
echo ' launch_agents: Install launchd plists to ~/Library/LaunchAgents/'
|
||||
echo ' terminfo: Install terminfo.'
|
||||
echo ' help: Display this message.'
|
||||
}
|
||||
|
||||
@@ -261,12 +284,18 @@ case "$1" in
|
||||
private)
|
||||
install_private
|
||||
;;
|
||||
agentic)
|
||||
install_agentic
|
||||
;;
|
||||
homebrew | brew)
|
||||
install_homebrew
|
||||
;;
|
||||
rbenv)
|
||||
install_rbenv
|
||||
;;
|
||||
rustup | rust)
|
||||
install_rustup
|
||||
;;
|
||||
launch_agents | launch-agents | agents)
|
||||
install_launch_agents
|
||||
;;
|
||||
|
||||
6
irbrc
6
irbrc
@@ -1,4 +1,4 @@
|
||||
require 'irb/completion'
|
||||
require 'irb/ext/save-history'
|
||||
IRB.conf[:SAVE_HISTORY] = 1000
|
||||
IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb-history"
|
||||
IRB.conf[:USE_AUTOCOMPLETE] = false
|
||||
IRB.conf[:USE_MULTILINE] = false if ENV['INSIDE_EMACS']
|
||||
IRB.conf[:USE_READLINE] = false if ENV['INSIDE_EMACS']
|
||||
|
||||
835
karabiner/emacs-control-keys-rev-11-custom.json
Normal file
835
karabiner/emacs-control-keys-rev-11-custom.json
Normal file
@@ -0,0 +1,835 @@
|
||||
{
|
||||
"description": "Emacs key bindings [control+keys] (rev 11) [custom]",
|
||||
"manipulators": [
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^org\\.gnu\\.Emacs$",
|
||||
"^org\\.gnu\\.AquamacsEmacs$",
|
||||
"^org\\.gnu\\.Aquamacs$",
|
||||
"^org\\.pqrs\\.unknownapp\\.conkeror$",
|
||||
"^com\\.microsoft\\.rdc$",
|
||||
"^com\\.microsoft\\.rdc\\.",
|
||||
"^net\\.sf\\.cord$",
|
||||
"^com\\.thinomenon\\.RemoteDesktopConnection$",
|
||||
"^com\\.itap-mobile\\.qmote$",
|
||||
"^com\\.nulana\\.remotixmac$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer\\.",
|
||||
"^com\\.teamviewer\\.TeamViewer$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.2X\\.Client\\.Mac$",
|
||||
"^com\\.OpenText\\.Exceed-TurboX-Client$",
|
||||
"^com\\.realvnc\\.vncviewer$",
|
||||
"^com\\.citrix\\.receiver\\.icaviewer",
|
||||
"^com\\.apple\\.Terminal$",
|
||||
"^com\\.googlecode\\.iterm2$",
|
||||
"^co\\.zeit\\.hyperterm$",
|
||||
"^co\\.zeit\\.hyper$",
|
||||
"^io\\.alacritty$",
|
||||
"^org\\.alacritty$",
|
||||
"^net\\.kovidgoyal\\.kitty$",
|
||||
"^com\\.mitchellh\\.ghostty$",
|
||||
"^org\\.vim\\.",
|
||||
"^com\\.qvacua\\.VimR$",
|
||||
"^com\\.vmware\\.fusion$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.vmware\\.view$",
|
||||
"^com\\.parallels\\.desktop$",
|
||||
"^com\\.parallels\\.vm$",
|
||||
"^com\\.parallels\\.desktop\\.console$",
|
||||
"^org\\.virtualbox\\.app\\.VirtualBoxVM$",
|
||||
"^com\\.citrix\\.XenAppViewer$",
|
||||
"^com\\.vmware\\.proxyApp\\.",
|
||||
"^com\\.parallels\\.winapp\\.",
|
||||
"^com\\.utmapp\\.UTM$",
|
||||
"^org\\.x\\.X11$",
|
||||
"^com\\.apple\\.x11$",
|
||||
"^org\\.macosforge\\.xquartz\\.X11$",
|
||||
"^org\\.macports\\.X11$",
|
||||
"^com\\.sublimetext\\.",
|
||||
"^com\\.microsoft\\.VSCode$",
|
||||
"^com\\.todesktop\\.",
|
||||
"^dev\\.warp\\.Warp"
|
||||
],
|
||||
"type": "frontmost_application_unless"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "d",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"option"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "delete_forward"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^org\\.gnu\\.Emacs$",
|
||||
"^org\\.gnu\\.AquamacsEmacs$",
|
||||
"^org\\.gnu\\.Aquamacs$",
|
||||
"^org\\.pqrs\\.unknownapp\\.conkeror$",
|
||||
"^com\\.microsoft\\.rdc$",
|
||||
"^com\\.microsoft\\.rdc\\.",
|
||||
"^net\\.sf\\.cord$",
|
||||
"^com\\.thinomenon\\.RemoteDesktopConnection$",
|
||||
"^com\\.itap-mobile\\.qmote$",
|
||||
"^com\\.nulana\\.remotixmac$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer\\.",
|
||||
"^com\\.teamviewer\\.TeamViewer$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.2X\\.Client\\.Mac$",
|
||||
"^com\\.OpenText\\.Exceed-TurboX-Client$",
|
||||
"^com\\.realvnc\\.vncviewer$",
|
||||
"^com\\.citrix\\.receiver\\.icaviewer",
|
||||
"^com\\.apple\\.Terminal$",
|
||||
"^com\\.googlecode\\.iterm2$",
|
||||
"^co\\.zeit\\.hyperterm$",
|
||||
"^co\\.zeit\\.hyper$",
|
||||
"^io\\.alacritty$",
|
||||
"^org\\.alacritty$",
|
||||
"^net\\.kovidgoyal\\.kitty$",
|
||||
"^com\\.mitchellh\\.ghostty$",
|
||||
"^org\\.vim\\.",
|
||||
"^com\\.qvacua\\.VimR$",
|
||||
"^com\\.vmware\\.fusion$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.vmware\\.view$",
|
||||
"^com\\.parallels\\.desktop$",
|
||||
"^com\\.parallels\\.vm$",
|
||||
"^com\\.parallels\\.desktop\\.console$",
|
||||
"^org\\.virtualbox\\.app\\.VirtualBoxVM$",
|
||||
"^com\\.citrix\\.XenAppViewer$",
|
||||
"^com\\.vmware\\.proxyApp\\.",
|
||||
"^com\\.parallels\\.winapp\\.",
|
||||
"^com\\.utmapp\\.UTM$",
|
||||
"^org\\.x\\.X11$",
|
||||
"^com\\.apple\\.x11$",
|
||||
"^org\\.macosforge\\.xquartz\\.X11$",
|
||||
"^org\\.macports\\.X11$",
|
||||
"^com\\.sublimetext\\.",
|
||||
"^com\\.microsoft\\.VSCode$",
|
||||
"^com\\.todesktop\\.",
|
||||
"^dev\\.warp\\.Warp"
|
||||
],
|
||||
"type": "frontmost_application_unless"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "h",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"option"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "delete_or_backspace"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^org\\.gnu\\.Emacs$",
|
||||
"^org\\.gnu\\.AquamacsEmacs$",
|
||||
"^org\\.gnu\\.Aquamacs$",
|
||||
"^org\\.pqrs\\.unknownapp\\.conkeror$",
|
||||
"^com\\.microsoft\\.rdc$",
|
||||
"^com\\.microsoft\\.rdc\\.",
|
||||
"^net\\.sf\\.cord$",
|
||||
"^com\\.thinomenon\\.RemoteDesktopConnection$",
|
||||
"^com\\.itap-mobile\\.qmote$",
|
||||
"^com\\.nulana\\.remotixmac$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer\\.",
|
||||
"^com\\.teamviewer\\.TeamViewer$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.2X\\.Client\\.Mac$",
|
||||
"^com\\.OpenText\\.Exceed-TurboX-Client$",
|
||||
"^com\\.realvnc\\.vncviewer$",
|
||||
"^com\\.citrix\\.receiver\\.icaviewer",
|
||||
"^com\\.apple\\.Terminal$",
|
||||
"^com\\.googlecode\\.iterm2$",
|
||||
"^co\\.zeit\\.hyperterm$",
|
||||
"^co\\.zeit\\.hyper$",
|
||||
"^io\\.alacritty$",
|
||||
"^org\\.alacritty$",
|
||||
"^net\\.kovidgoyal\\.kitty$",
|
||||
"^com\\.mitchellh\\.ghostty$",
|
||||
"^org\\.vim\\.",
|
||||
"^com\\.qvacua\\.VimR$",
|
||||
"^com\\.vmware\\.fusion$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.vmware\\.view$",
|
||||
"^com\\.parallels\\.desktop$",
|
||||
"^com\\.parallels\\.vm$",
|
||||
"^com\\.parallels\\.desktop\\.console$",
|
||||
"^org\\.virtualbox\\.app\\.VirtualBoxVM$",
|
||||
"^com\\.citrix\\.XenAppViewer$",
|
||||
"^com\\.vmware\\.proxyApp\\.",
|
||||
"^com\\.parallels\\.winapp\\.",
|
||||
"^com\\.utmapp\\.UTM$",
|
||||
"^org\\.x\\.X11$",
|
||||
"^com\\.apple\\.x11$",
|
||||
"^org\\.macosforge\\.xquartz\\.X11$",
|
||||
"^org\\.macports\\.X11$",
|
||||
"^com\\.sublimetext\\.",
|
||||
"^com\\.microsoft\\.VSCode$",
|
||||
"^com\\.todesktop\\.",
|
||||
"^dev\\.warp\\.Warp"
|
||||
],
|
||||
"type": "frontmost_application_unless"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "i",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "tab"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"keyboard_types": [
|
||||
"ansi",
|
||||
"iso"
|
||||
],
|
||||
"type": "keyboard_type_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "open_bracket",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "escape"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"keyboard_types": [
|
||||
"jis"
|
||||
],
|
||||
"type": "keyboard_type_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "close_bracket",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "escape"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"from": {
|
||||
"key_code": "m",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift",
|
||||
"option"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "return_or_enter"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^org\\.gnu\\.Emacs$",
|
||||
"^org\\.gnu\\.AquamacsEmacs$",
|
||||
"^org\\.gnu\\.Aquamacs$",
|
||||
"^org\\.pqrs\\.unknownapp\\.conkeror$",
|
||||
"^com\\.microsoft\\.rdc$",
|
||||
"^com\\.microsoft\\.rdc\\.",
|
||||
"^net\\.sf\\.cord$",
|
||||
"^com\\.thinomenon\\.RemoteDesktopConnection$",
|
||||
"^com\\.itap-mobile\\.qmote$",
|
||||
"^com\\.nulana\\.remotixmac$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer\\.",
|
||||
"^com\\.teamviewer\\.TeamViewer$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.2X\\.Client\\.Mac$",
|
||||
"^com\\.OpenText\\.Exceed-TurboX-Client$",
|
||||
"^com\\.realvnc\\.vncviewer$",
|
||||
"^com\\.citrix\\.receiver\\.icaviewer",
|
||||
"^com\\.apple\\.Terminal$",
|
||||
"^com\\.googlecode\\.iterm2$",
|
||||
"^co\\.zeit\\.hyperterm$",
|
||||
"^co\\.zeit\\.hyper$",
|
||||
"^io\\.alacritty$",
|
||||
"^org\\.alacritty$",
|
||||
"^net\\.kovidgoyal\\.kitty$",
|
||||
"^com\\.mitchellh\\.ghostty$",
|
||||
"^org\\.vim\\.",
|
||||
"^com\\.qvacua\\.VimR$",
|
||||
"^com\\.vmware\\.fusion$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.vmware\\.view$",
|
||||
"^com\\.parallels\\.desktop$",
|
||||
"^com\\.parallels\\.vm$",
|
||||
"^com\\.parallels\\.desktop\\.console$",
|
||||
"^org\\.virtualbox\\.app\\.VirtualBoxVM$",
|
||||
"^com\\.citrix\\.XenAppViewer$",
|
||||
"^com\\.vmware\\.proxyApp\\.",
|
||||
"^com\\.parallels\\.winapp\\.",
|
||||
"^com\\.utmapp\\.UTM$",
|
||||
"^org\\.x\\.X11$",
|
||||
"^com\\.apple\\.x11$",
|
||||
"^org\\.macosforge\\.xquartz\\.X11$",
|
||||
"^org\\.macports\\.X11$",
|
||||
"^com\\.sublimetext\\.",
|
||||
"^com\\.microsoft\\.VSCode$",
|
||||
"^com\\.todesktop\\.",
|
||||
"^dev\\.warp\\.Warp"
|
||||
],
|
||||
"type": "frontmost_application_unless"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "b",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift",
|
||||
"option"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "left_arrow"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^org\\.gnu\\.Emacs$",
|
||||
"^org\\.gnu\\.AquamacsEmacs$",
|
||||
"^org\\.gnu\\.Aquamacs$",
|
||||
"^org\\.pqrs\\.unknownapp\\.conkeror$",
|
||||
"^com\\.microsoft\\.rdc$",
|
||||
"^com\\.microsoft\\.rdc\\.",
|
||||
"^net\\.sf\\.cord$",
|
||||
"^com\\.thinomenon\\.RemoteDesktopConnection$",
|
||||
"^com\\.itap-mobile\\.qmote$",
|
||||
"^com\\.nulana\\.remotixmac$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer\\.",
|
||||
"^com\\.teamviewer\\.TeamViewer$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.2X\\.Client\\.Mac$",
|
||||
"^com\\.OpenText\\.Exceed-TurboX-Client$",
|
||||
"^com\\.realvnc\\.vncviewer$",
|
||||
"^com\\.citrix\\.receiver\\.icaviewer",
|
||||
"^com\\.apple\\.Terminal$",
|
||||
"^com\\.googlecode\\.iterm2$",
|
||||
"^co\\.zeit\\.hyperterm$",
|
||||
"^co\\.zeit\\.hyper$",
|
||||
"^io\\.alacritty$",
|
||||
"^org\\.alacritty$",
|
||||
"^net\\.kovidgoyal\\.kitty$",
|
||||
"^com\\.mitchellh\\.ghostty$",
|
||||
"^org\\.vim\\.",
|
||||
"^com\\.qvacua\\.VimR$",
|
||||
"^com\\.vmware\\.fusion$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.vmware\\.view$",
|
||||
"^com\\.parallels\\.desktop$",
|
||||
"^com\\.parallels\\.vm$",
|
||||
"^com\\.parallels\\.desktop\\.console$",
|
||||
"^org\\.virtualbox\\.app\\.VirtualBoxVM$",
|
||||
"^com\\.citrix\\.XenAppViewer$",
|
||||
"^com\\.vmware\\.proxyApp\\.",
|
||||
"^com\\.parallels\\.winapp\\.",
|
||||
"^com\\.utmapp\\.UTM$",
|
||||
"^org\\.x\\.X11$",
|
||||
"^com\\.apple\\.x11$",
|
||||
"^org\\.macosforge\\.xquartz\\.X11$",
|
||||
"^org\\.macports\\.X11$",
|
||||
"^com\\.sublimetext\\.",
|
||||
"^com\\.microsoft\\.VSCode$",
|
||||
"^com\\.todesktop\\.",
|
||||
"^dev\\.warp\\.Warp"
|
||||
],
|
||||
"type": "frontmost_application_unless"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "f",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift",
|
||||
"option"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "right_arrow"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^org\\.gnu\\.Emacs$",
|
||||
"^org\\.gnu\\.AquamacsEmacs$",
|
||||
"^org\\.gnu\\.Aquamacs$",
|
||||
"^org\\.pqrs\\.unknownapp\\.conkeror$",
|
||||
"^com\\.microsoft\\.rdc$",
|
||||
"^com\\.microsoft\\.rdc\\.",
|
||||
"^net\\.sf\\.cord$",
|
||||
"^com\\.thinomenon\\.RemoteDesktopConnection$",
|
||||
"^com\\.itap-mobile\\.qmote$",
|
||||
"^com\\.nulana\\.remotixmac$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer\\.",
|
||||
"^com\\.teamviewer\\.TeamViewer$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.2X\\.Client\\.Mac$",
|
||||
"^com\\.OpenText\\.Exceed-TurboX-Client$",
|
||||
"^com\\.realvnc\\.vncviewer$",
|
||||
"^com\\.citrix\\.receiver\\.icaviewer",
|
||||
"^com\\.apple\\.Terminal$",
|
||||
"^com\\.googlecode\\.iterm2$",
|
||||
"^co\\.zeit\\.hyperterm$",
|
||||
"^co\\.zeit\\.hyper$",
|
||||
"^io\\.alacritty$",
|
||||
"^org\\.alacritty$",
|
||||
"^net\\.kovidgoyal\\.kitty$",
|
||||
"^com\\.mitchellh\\.ghostty$",
|
||||
"^org\\.vim\\.",
|
||||
"^com\\.qvacua\\.VimR$",
|
||||
"^com\\.vmware\\.fusion$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.vmware\\.view$",
|
||||
"^com\\.parallels\\.desktop$",
|
||||
"^com\\.parallels\\.vm$",
|
||||
"^com\\.parallels\\.desktop\\.console$",
|
||||
"^org\\.virtualbox\\.app\\.VirtualBoxVM$",
|
||||
"^com\\.citrix\\.XenAppViewer$",
|
||||
"^com\\.vmware\\.proxyApp\\.",
|
||||
"^com\\.parallels\\.winapp\\.",
|
||||
"^com\\.utmapp\\.UTM$",
|
||||
"^org\\.x\\.X11$",
|
||||
"^com\\.apple\\.x11$",
|
||||
"^org\\.macosforge\\.xquartz\\.X11$",
|
||||
"^org\\.macports\\.X11$",
|
||||
"^com\\.sublimetext\\.",
|
||||
"^com\\.microsoft\\.VSCode$",
|
||||
"^com\\.todesktop\\.",
|
||||
"^dev\\.warp\\.Warp"
|
||||
],
|
||||
"type": "frontmost_application_unless"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "n",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift",
|
||||
"option"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "down_arrow"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^org\\.gnu\\.Emacs$",
|
||||
"^org\\.gnu\\.AquamacsEmacs$",
|
||||
"^org\\.gnu\\.Aquamacs$",
|
||||
"^org\\.pqrs\\.unknownapp\\.conkeror$",
|
||||
"^com\\.microsoft\\.rdc$",
|
||||
"^com\\.microsoft\\.rdc\\.",
|
||||
"^net\\.sf\\.cord$",
|
||||
"^com\\.thinomenon\\.RemoteDesktopConnection$",
|
||||
"^com\\.itap-mobile\\.qmote$",
|
||||
"^com\\.nulana\\.remotixmac$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer\\.",
|
||||
"^com\\.teamviewer\\.TeamViewer$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.2X\\.Client\\.Mac$",
|
||||
"^com\\.OpenText\\.Exceed-TurboX-Client$",
|
||||
"^com\\.realvnc\\.vncviewer$",
|
||||
"^com\\.citrix\\.receiver\\.icaviewer",
|
||||
"^com\\.apple\\.Terminal$",
|
||||
"^com\\.googlecode\\.iterm2$",
|
||||
"^co\\.zeit\\.hyperterm$",
|
||||
"^co\\.zeit\\.hyper$",
|
||||
"^io\\.alacritty$",
|
||||
"^org\\.alacritty$",
|
||||
"^net\\.kovidgoyal\\.kitty$",
|
||||
"^com\\.mitchellh\\.ghostty$",
|
||||
"^org\\.vim\\.",
|
||||
"^com\\.qvacua\\.VimR$",
|
||||
"^com\\.vmware\\.fusion$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.vmware\\.view$",
|
||||
"^com\\.parallels\\.desktop$",
|
||||
"^com\\.parallels\\.vm$",
|
||||
"^com\\.parallels\\.desktop\\.console$",
|
||||
"^org\\.virtualbox\\.app\\.VirtualBoxVM$",
|
||||
"^com\\.citrix\\.XenAppViewer$",
|
||||
"^com\\.vmware\\.proxyApp\\.",
|
||||
"^com\\.parallels\\.winapp\\.",
|
||||
"^com\\.utmapp\\.UTM$",
|
||||
"^org\\.x\\.X11$",
|
||||
"^com\\.apple\\.x11$",
|
||||
"^org\\.macosforge\\.xquartz\\.X11$",
|
||||
"^org\\.macports\\.X11$",
|
||||
"^com\\.sublimetext\\.",
|
||||
"^com\\.microsoft\\.VSCode$",
|
||||
"^com\\.todesktop\\.",
|
||||
"^dev\\.warp\\.Warp"
|
||||
],
|
||||
"type": "frontmost_application_unless"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "p",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift",
|
||||
"option"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "up_arrow"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^org\\.gnu\\.Emacs$",
|
||||
"^org\\.gnu\\.AquamacsEmacs$",
|
||||
"^org\\.gnu\\.Aquamacs$",
|
||||
"^org\\.pqrs\\.unknownapp\\.conkeror$",
|
||||
"^com\\.microsoft\\.rdc$",
|
||||
"^com\\.microsoft\\.rdc\\.",
|
||||
"^net\\.sf\\.cord$",
|
||||
"^com\\.thinomenon\\.RemoteDesktopConnection$",
|
||||
"^com\\.itap-mobile\\.qmote$",
|
||||
"^com\\.nulana\\.remotixmac$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer\\.",
|
||||
"^com\\.teamviewer\\.TeamViewer$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.2X\\.Client\\.Mac$",
|
||||
"^com\\.OpenText\\.Exceed-TurboX-Client$",
|
||||
"^com\\.realvnc\\.vncviewer$",
|
||||
"^com\\.citrix\\.receiver\\.icaviewer",
|
||||
"^com\\.apple\\.Terminal$",
|
||||
"^com\\.googlecode\\.iterm2$",
|
||||
"^co\\.zeit\\.hyperterm$",
|
||||
"^co\\.zeit\\.hyper$",
|
||||
"^io\\.alacritty$",
|
||||
"^org\\.alacritty$",
|
||||
"^net\\.kovidgoyal\\.kitty$",
|
||||
"^com\\.mitchellh\\.ghostty$",
|
||||
"^org\\.vim\\.",
|
||||
"^com\\.qvacua\\.VimR$",
|
||||
"^com\\.vmware\\.fusion$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.vmware\\.view$",
|
||||
"^com\\.parallels\\.desktop$",
|
||||
"^com\\.parallels\\.vm$",
|
||||
"^com\\.parallels\\.desktop\\.console$",
|
||||
"^org\\.virtualbox\\.app\\.VirtualBoxVM$",
|
||||
"^com\\.citrix\\.XenAppViewer$",
|
||||
"^com\\.vmware\\.proxyApp\\.",
|
||||
"^com\\.parallels\\.winapp\\.",
|
||||
"^com\\.utmapp\\.UTM$",
|
||||
"^org\\.x\\.X11$",
|
||||
"^com\\.apple\\.x11$",
|
||||
"^org\\.macosforge\\.xquartz\\.X11$",
|
||||
"^org\\.macports\\.X11$",
|
||||
"^com\\.sublimetext\\.",
|
||||
"^com\\.microsoft\\.VSCode$",
|
||||
"^com\\.todesktop\\.",
|
||||
"^dev\\.warp\\.Warp"
|
||||
],
|
||||
"type": "frontmost_application_unless"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "v",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "page_down"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^com\\.microsoft\\.Excel$",
|
||||
"^com\\.microsoft\\.Powerpoint$",
|
||||
"^com\\.microsoft\\.Word$"
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "a",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "home"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^com\\.microsoft\\.Excel$",
|
||||
"^com\\.microsoft\\.Powerpoint$",
|
||||
"^com\\.microsoft\\.Word$"
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "e",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "end"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^com\\.microsoft\\.Excel$",
|
||||
"^com\\.microsoft\\.Powerpoint$",
|
||||
"^com\\.microsoft\\.Word$"
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "k",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "end",
|
||||
"modifiers": [
|
||||
"left_shift"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key_code": "delete_forward"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^org\\.eclipse\\.platform\\.ide$"
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "a",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "left_arrow",
|
||||
"modifiers": [
|
||||
"left_command"
|
||||
]
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^org\\.eclipse\\.platform\\.ide$"
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "e",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "right_arrow",
|
||||
"modifiers": [
|
||||
"left_command"
|
||||
]
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
}
|
||||
]
|
||||
}
|
||||
75
karabiner/emacs-ctrl-g-to-esc.json
Normal file
75
karabiner/emacs-ctrl-g-to-esc.json
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"description": "Emacs style ctrl+g to esc (rev 1)",
|
||||
"manipulators": [
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^org\\.gnu\\.Emacs$",
|
||||
"^org\\.gnu\\.AquamacsEmacs$",
|
||||
"^org\\.gnu\\.Aquamacs$",
|
||||
"^org\\.pqrs\\.unknownapp\\.conkeror$",
|
||||
"^com\\.microsoft\\.rdc$",
|
||||
"^com\\.microsoft\\.rdc\\.",
|
||||
"^net\\.sf\\.cord$",
|
||||
"^com\\.thinomenon\\.RemoteDesktopConnection$",
|
||||
"^com\\.itap-mobile\\.qmote$",
|
||||
"^com\\.nulana\\.remotixmac$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer\\.",
|
||||
"^com\\.teamviewer\\.TeamViewer$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.2X\\.Client\\.Mac$",
|
||||
"^com\\.OpenText\\.Exceed-TurboX-Client$",
|
||||
"^com\\.realvnc\\.vncviewer$",
|
||||
"^com\\.citrix\\.receiver\\.icaviewer",
|
||||
"^com\\.apple\\.Terminal$",
|
||||
"^com\\.googlecode\\.iterm2$",
|
||||
"^co\\.zeit\\.hyperterm$",
|
||||
"^co\\.zeit\\.hyper$",
|
||||
"^io\\.alacritty$",
|
||||
"^org\\.alacritty$",
|
||||
"^net\\.kovidgoyal\\.kitty$",
|
||||
"^org\\.vim\\.",
|
||||
"^com\\.qvacua\\.VimR$",
|
||||
"^com\\.vmware\\.fusion$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.vmware\\.view$",
|
||||
"^com\\.parallels\\.desktop$",
|
||||
"^com\\.parallels\\.vm$",
|
||||
"^com\\.parallels\\.desktop\\.console$",
|
||||
"^org\\.virtualbox\\.app\\.VirtualBoxVM$",
|
||||
"^com\\.citrix\\.XenAppViewer$",
|
||||
"^com\\.vmware\\.proxyApp\\.",
|
||||
"^com\\.parallels\\.winapp\\.",
|
||||
"^com\\.utmapp\\.UTM$",
|
||||
"^org\\.x\\.X11$",
|
||||
"^com\\.apple\\.x11$",
|
||||
"^org\\.macosforge\\.xquartz\\.X11$",
|
||||
"^org\\.macports\\.X11$",
|
||||
"^com\\.sublimetext\\.",
|
||||
"^com\\.microsoft\\.VSCode$"
|
||||
],
|
||||
"type": "frontmost_application_unless"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "g",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "escape"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
}
|
||||
]
|
||||
}
|
||||
309
karabiner/emacs-option-keys-rev-5-custom.json
Normal file
309
karabiner/emacs-option-keys-rev-5-custom.json
Normal file
@@ -0,0 +1,309 @@
|
||||
{
|
||||
"description": "Emacs key bindings [option+keys] (rev 5) [custom]",
|
||||
"manipulators": [
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^org\\.gnu\\.Emacs$",
|
||||
"^org\\.gnu\\.AquamacsEmacs$",
|
||||
"^org\\.gnu\\.Aquamacs$",
|
||||
"^org\\.pqrs\\.unknownapp\\.conkeror$",
|
||||
"^com\\.microsoft\\.rdc$",
|
||||
"^com\\.microsoft\\.rdc\\.",
|
||||
"^net\\.sf\\.cord$",
|
||||
"^com\\.thinomenon\\.RemoteDesktopConnection$",
|
||||
"^com\\.itap-mobile\\.qmote$",
|
||||
"^com\\.nulana\\.remotixmac$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer\\.",
|
||||
"^com\\.teamviewer\\.TeamViewer$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.2X\\.Client\\.Mac$",
|
||||
"^com\\.OpenText\\.Exceed-TurboX-Client$",
|
||||
"^com\\.realvnc\\.vncviewer$",
|
||||
"^com\\.citrix\\.receiver\\.icaviewer",
|
||||
"^com\\.apple\\.Terminal$",
|
||||
"^com\\.googlecode\\.iterm2$",
|
||||
"^co\\.zeit\\.hyperterm$",
|
||||
"^co\\.zeit\\.hyper$",
|
||||
"^io\\.alacritty$",
|
||||
"^org\\.alacritty$",
|
||||
"^net\\.kovidgoyal\\.kitty$",
|
||||
"^com\\.mitchellh\\.ghostty$",
|
||||
"^org\\.vim\\.",
|
||||
"^com\\.qvacua\\.VimR$",
|
||||
"^com\\.vmware\\.fusion$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.vmware\\.view$",
|
||||
"^com\\.parallels\\.desktop$",
|
||||
"^com\\.parallels\\.vm$",
|
||||
"^com\\.parallels\\.desktop\\.console$",
|
||||
"^org\\.virtualbox\\.app\\.VirtualBoxVM$",
|
||||
"^com\\.citrix\\.XenAppViewer$",
|
||||
"^com\\.vmware\\.proxyApp\\.",
|
||||
"^com\\.parallels\\.winapp\\.",
|
||||
"^com\\.utmapp\\.UTM$",
|
||||
"^org\\.x\\.X11$",
|
||||
"^com\\.apple\\.x11$",
|
||||
"^org\\.macosforge\\.xquartz\\.X11$",
|
||||
"^org\\.macports\\.X11$",
|
||||
"^com\\.sublimetext\\.",
|
||||
"^com\\.microsoft\\.VSCode$",
|
||||
"^com\\.todesktop\\.",
|
||||
"^dev\\.warp\\.Warp"
|
||||
],
|
||||
"type": "frontmost_application_unless"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "v",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"option"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "page_up"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^org\\.gnu\\.Emacs$",
|
||||
"^org\\.gnu\\.AquamacsEmacs$",
|
||||
"^org\\.gnu\\.Aquamacs$",
|
||||
"^org\\.pqrs\\.unknownapp\\.conkeror$",
|
||||
"^com\\.microsoft\\.rdc$",
|
||||
"^com\\.microsoft\\.rdc\\.",
|
||||
"^net\\.sf\\.cord$",
|
||||
"^com\\.thinomenon\\.RemoteDesktopConnection$",
|
||||
"^com\\.itap-mobile\\.qmote$",
|
||||
"^com\\.nulana\\.remotixmac$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer\\.",
|
||||
"^com\\.teamviewer\\.TeamViewer$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.2X\\.Client\\.Mac$",
|
||||
"^com\\.OpenText\\.Exceed-TurboX-Client$",
|
||||
"^com\\.realvnc\\.vncviewer$",
|
||||
"^com\\.citrix\\.receiver\\.icaviewer",
|
||||
"^com\\.apple\\.Terminal$",
|
||||
"^com\\.googlecode\\.iterm2$",
|
||||
"^co\\.zeit\\.hyperterm$",
|
||||
"^co\\.zeit\\.hyper$",
|
||||
"^io\\.alacritty$",
|
||||
"^org\\.alacritty$",
|
||||
"^net\\.kovidgoyal\\.kitty$",
|
||||
"^com\\.mitchellh\\.ghostty$",
|
||||
"^org\\.vim\\.",
|
||||
"^com\\.qvacua\\.VimR$",
|
||||
"^com\\.vmware\\.fusion$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.vmware\\.view$",
|
||||
"^com\\.parallels\\.desktop$",
|
||||
"^com\\.parallels\\.vm$",
|
||||
"^com\\.parallels\\.desktop\\.console$",
|
||||
"^org\\.virtualbox\\.app\\.VirtualBoxVM$",
|
||||
"^com\\.citrix\\.XenAppViewer$",
|
||||
"^com\\.vmware\\.proxyApp\\.",
|
||||
"^com\\.parallels\\.winapp\\.",
|
||||
"^com\\.utmapp\\.UTM$",
|
||||
"^org\\.x\\.X11$",
|
||||
"^com\\.apple\\.x11$",
|
||||
"^org\\.macosforge\\.xquartz\\.X11$",
|
||||
"^org\\.macports\\.X11$",
|
||||
"^com\\.sublimetext\\.",
|
||||
"^com\\.microsoft\\.VSCode$",
|
||||
"^com\\.todesktop\\.",
|
||||
"^dev\\.warp\\.Warp"
|
||||
],
|
||||
"type": "frontmost_application_unless"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "b",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"option"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "left_arrow",
|
||||
"modifiers": [
|
||||
"left_option"
|
||||
]
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^org\\.gnu\\.Emacs$",
|
||||
"^org\\.gnu\\.AquamacsEmacs$",
|
||||
"^org\\.gnu\\.Aquamacs$",
|
||||
"^org\\.pqrs\\.unknownapp\\.conkeror$",
|
||||
"^com\\.microsoft\\.rdc$",
|
||||
"^com\\.microsoft\\.rdc\\.",
|
||||
"^net\\.sf\\.cord$",
|
||||
"^com\\.thinomenon\\.RemoteDesktopConnection$",
|
||||
"^com\\.itap-mobile\\.qmote$",
|
||||
"^com\\.nulana\\.remotixmac$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer\\.",
|
||||
"^com\\.teamviewer\\.TeamViewer$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.2X\\.Client\\.Mac$",
|
||||
"^com\\.OpenText\\.Exceed-TurboX-Client$",
|
||||
"^com\\.realvnc\\.vncviewer$",
|
||||
"^com\\.citrix\\.receiver\\.icaviewer",
|
||||
"^com\\.apple\\.Terminal$",
|
||||
"^com\\.googlecode\\.iterm2$",
|
||||
"^co\\.zeit\\.hyperterm$",
|
||||
"^co\\.zeit\\.hyper$",
|
||||
"^io\\.alacritty$",
|
||||
"^org\\.alacritty$",
|
||||
"^net\\.kovidgoyal\\.kitty$",
|
||||
"^com\\.mitchellh\\.ghostty$",
|
||||
"^org\\.vim\\.",
|
||||
"^com\\.qvacua\\.VimR$",
|
||||
"^com\\.vmware\\.fusion$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.vmware\\.view$",
|
||||
"^com\\.parallels\\.desktop$",
|
||||
"^com\\.parallels\\.vm$",
|
||||
"^com\\.parallels\\.desktop\\.console$",
|
||||
"^org\\.virtualbox\\.app\\.VirtualBoxVM$",
|
||||
"^com\\.citrix\\.XenAppViewer$",
|
||||
"^com\\.vmware\\.proxyApp\\.",
|
||||
"^com\\.parallels\\.winapp\\.",
|
||||
"^com\\.utmapp\\.UTM$",
|
||||
"^org\\.x\\.X11$",
|
||||
"^com\\.apple\\.x11$",
|
||||
"^org\\.macosforge\\.xquartz\\.X11$",
|
||||
"^org\\.macports\\.X11$",
|
||||
"^com\\.sublimetext\\.",
|
||||
"^com\\.microsoft\\.VSCode$",
|
||||
"^com\\.todesktop\\.",
|
||||
"^dev\\.warp\\.Warp"
|
||||
],
|
||||
"type": "frontmost_application_unless"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "f",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"option"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "right_arrow",
|
||||
"modifiers": [
|
||||
"left_option"
|
||||
]
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^org\\.gnu\\.Emacs$",
|
||||
"^org\\.gnu\\.AquamacsEmacs$",
|
||||
"^org\\.gnu\\.Aquamacs$",
|
||||
"^org\\.pqrs\\.unknownapp\\.conkeror$",
|
||||
"^com\\.microsoft\\.rdc$",
|
||||
"^com\\.microsoft\\.rdc\\.",
|
||||
"^net\\.sf\\.cord$",
|
||||
"^com\\.thinomenon\\.RemoteDesktopConnection$",
|
||||
"^com\\.itap-mobile\\.qmote$",
|
||||
"^com\\.nulana\\.remotixmac$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer$",
|
||||
"^com\\.p5sys\\.jump\\.mac\\.viewer\\.",
|
||||
"^com\\.teamviewer\\.TeamViewer$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.2X\\.Client\\.Mac$",
|
||||
"^com\\.OpenText\\.Exceed-TurboX-Client$",
|
||||
"^com\\.realvnc\\.vncviewer$",
|
||||
"^com\\.citrix\\.receiver\\.icaviewer",
|
||||
"^com\\.apple\\.Terminal$",
|
||||
"^com\\.googlecode\\.iterm2$",
|
||||
"^co\\.zeit\\.hyperterm$",
|
||||
"^co\\.zeit\\.hyper$",
|
||||
"^io\\.alacritty$",
|
||||
"^org\\.alacritty$",
|
||||
"^net\\.kovidgoyal\\.kitty$",
|
||||
"^com\\.mitchellh\\.ghostty$",
|
||||
"^org\\.vim\\.",
|
||||
"^com\\.qvacua\\.VimR$",
|
||||
"^com\\.vmware\\.fusion$",
|
||||
"^com\\.vmware\\.horizon$",
|
||||
"^com\\.vmware\\.view$",
|
||||
"^com\\.parallels\\.desktop$",
|
||||
"^com\\.parallels\\.vm$",
|
||||
"^com\\.parallels\\.desktop\\.console$",
|
||||
"^org\\.virtualbox\\.app\\.VirtualBoxVM$",
|
||||
"^com\\.citrix\\.XenAppViewer$",
|
||||
"^com\\.vmware\\.proxyApp\\.",
|
||||
"^com\\.parallels\\.winapp\\.",
|
||||
"^com\\.utmapp\\.UTM$",
|
||||
"^org\\.x\\.X11$",
|
||||
"^com\\.apple\\.x11$",
|
||||
"^org\\.macosforge\\.xquartz\\.X11$",
|
||||
"^org\\.macports\\.X11$",
|
||||
"^com\\.sublimetext\\.",
|
||||
"^com\\.microsoft\\.VSCode$",
|
||||
"^com\\.todesktop\\.",
|
||||
"^dev\\.warp\\.Warp"
|
||||
],
|
||||
"type": "frontmost_application_unless"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "d",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"option"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "delete_forward",
|
||||
"modifiers": [
|
||||
"left_option"
|
||||
]
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
}
|
||||
]
|
||||
}
|
||||
489
karabiner/vscode-keybinding-workarounds.json
Normal file
489
karabiner/vscode-keybinding-workarounds.json
Normal file
@@ -0,0 +1,489 @@
|
||||
{
|
||||
"description": "VSCode keybinding workarounds",
|
||||
"manipulators": [
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^com\\.exafunction\\.windsurf",
|
||||
"^com\\.microsoft\\.VSCode",
|
||||
"^com\\.todesktop\\."
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "i",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"option"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "up_arrow",
|
||||
"modifiers": [
|
||||
"left_option",
|
||||
"left_command"
|
||||
]
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^com\\.exafunction\\.windsurf",
|
||||
"^com\\.microsoft\\.VSCode",
|
||||
"^com\\.todesktop\\."
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "n",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"option"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "down_arrow",
|
||||
"modifiers": [
|
||||
"left_option",
|
||||
"left_command"
|
||||
]
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^com\\.exafunction\\.windsurf",
|
||||
"^com\\.microsoft\\.VSCode",
|
||||
"^com\\.todesktop\\."
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "e",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"option"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "right_arrow",
|
||||
"modifiers": [
|
||||
"left_option",
|
||||
"left_command"
|
||||
]
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^com\\.exafunction\\.windsurf",
|
||||
"^com\\.microsoft\\.VSCode",
|
||||
"^com\\.todesktop\\."
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "f",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"option"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "right_arrow",
|
||||
"modifiers": [
|
||||
"left_option"
|
||||
]
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^com\\.exafunction\\.windsurf",
|
||||
"^com\\.microsoft\\.VSCode",
|
||||
"^com\\.todesktop\\."
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "b",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"option"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "left_arrow",
|
||||
"modifiers": [
|
||||
"left_option"
|
||||
]
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^com\\.exafunction\\.windsurf",
|
||||
"^com\\.microsoft\\.VSCode",
|
||||
"^com\\.todesktop\\."
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "d",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"option"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "delete_forward",
|
||||
"modifiers": [
|
||||
"left_option"
|
||||
]
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^com\\.exafunction\\.windsurf",
|
||||
"^com\\.microsoft\\.VSCode",
|
||||
"^com\\.todesktop\\."
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "hyphen",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"option"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "z",
|
||||
"modifiers": [
|
||||
"left_command"
|
||||
]
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^com\\.exafunction\\.windsurf",
|
||||
"^com\\.microsoft\\.VSCode",
|
||||
"^com\\.todesktop\\."
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "hyphen",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"option",
|
||||
"shift"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "z",
|
||||
"modifiers": [
|
||||
"left_command",
|
||||
"left_shift"
|
||||
]
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^com\\.exafunction\\.windsurf",
|
||||
"^com\\.microsoft\\.VSCode",
|
||||
"^com\\.todesktop\\."
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "d",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "delete_forward"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^com\\.exafunction\\.windsurf",
|
||||
"^com\\.microsoft\\.VSCode",
|
||||
"^com\\.todesktop\\."
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "p",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "up_arrow"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^com\\.exafunction\\.windsurf",
|
||||
"^com\\.microsoft\\.VSCode",
|
||||
"^com\\.todesktop\\."
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "n",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "down_arrow"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^com\\.exafunction\\.windsurf",
|
||||
"^com\\.microsoft\\.VSCode",
|
||||
"^com\\.todesktop\\."
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "b",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "left_arrow"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^com\\.exafunction\\.windsurf",
|
||||
"^com\\.microsoft\\.VSCode",
|
||||
"^com\\.todesktop\\."
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "f",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"control"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock",
|
||||
"shift"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "right_arrow"
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^com\\.exafunction\\.windsurf",
|
||||
"^com\\.microsoft\\.VSCode",
|
||||
"^com\\.todesktop\\."
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "comma",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"option",
|
||||
"shift"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "up_arrow",
|
||||
"modifiers": [
|
||||
"left_command"
|
||||
]
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"bundle_identifiers": [
|
||||
"^com\\.exafunction\\.windsurf",
|
||||
"^com\\.microsoft\\.VSCode",
|
||||
"^com\\.todesktop\\."
|
||||
],
|
||||
"type": "frontmost_application_if"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"key_code": "period",
|
||||
"modifiers": {
|
||||
"mandatory": [
|
||||
"option",
|
||||
"shift"
|
||||
],
|
||||
"optional": [
|
||||
"caps_lock"
|
||||
]
|
||||
}
|
||||
},
|
||||
"to": [
|
||||
{
|
||||
"key_code": "down_arrow",
|
||||
"modifiers": [
|
||||
"left_command"
|
||||
]
|
||||
}
|
||||
],
|
||||
"type": "basic"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
<string>/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/sbin</string>
|
||||
<string>/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/sbin:/opt/homebrew/bin:/opt/homebrew/sbin</string>
|
||||
</dict>
|
||||
<key>StartCalendarInterval</key>
|
||||
<dict>
|
||||
|
||||
@@ -10,14 +10,14 @@
|
||||
<array>
|
||||
<string>sh</string>
|
||||
<string>-c</string>
|
||||
<string>$HOME/.dotfiles/bin/macos_battery_exporter > $HOME/.node_metrics/battery.prom</string>
|
||||
<string>macos-battery-exporter -n node -o $HOME/.node_metrics/battery.prom</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<false/>
|
||||
<true/>
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
<string>/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/sbin</string>
|
||||
<string>/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/sbin:/opt/homebrew/bin:/opt/homebrew/sbin</string>
|
||||
</dict>
|
||||
<key>StartInterval</key>
|
||||
<integer>30</integer>
|
||||
|
||||
1
logrotate.d/.gitignore
vendored
Normal file
1
logrotate.d/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.conf
|
||||
9
logrotate.d/homebrew.confx
Normal file
9
logrotate.d/homebrew.confx
Normal file
@@ -0,0 +1,9 @@
|
||||
$(find "$(brew --prefix)/var/log" -name '*.log' -exec echo '"{}"' \;) {
|
||||
daily
|
||||
size 5115k
|
||||
missingok
|
||||
rotate 7
|
||||
compress
|
||||
copytruncate
|
||||
notifempty
|
||||
}
|
||||
9
logrotate.d/projects.confx
Normal file
9
logrotate.d/projects.confx
Normal file
@@ -0,0 +1,9 @@
|
||||
$(find ~/Projects -name '*.log' -path '*/log/*' ! -path '*/vendor/bundle/ruby/*' ! -path '*/node_modules/*' -exec echo '"{}"' \;) {
|
||||
daily
|
||||
size 5115k
|
||||
missingok
|
||||
rotate 7
|
||||
compress
|
||||
copytruncate
|
||||
notifempty
|
||||
}
|
||||
20
markdownlint.yaml
Normal file
20
markdownlint.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/DavidAnson/markdownlint/main/schema/markdownlint-config-schema.json
|
||||
no-hard-tabs: # MD010
|
||||
# Allow hard-tabs in code blocks in the below languages.
|
||||
ignore_code_languages:
|
||||
- caddyfile
|
||||
- go
|
||||
- makefile
|
||||
|
||||
blanks-around-fences: # MD031
|
||||
# Don't force blank lines around code blocks in lists.
|
||||
list_items: false
|
||||
|
||||
line-length: # MD013
|
||||
# Allow lines up to 120 characters.
|
||||
line_length: 80
|
||||
code_blocks: true
|
||||
ignore_code_blocks: true
|
||||
code_block_line_length: 280
|
||||
tables: false
|
||||
@@ -20,7 +20,7 @@
|
||||
domain: com.apple.dock
|
||||
key: largesize
|
||||
type: float
|
||||
value: 70
|
||||
value: 65
|
||||
notify: restart Dock
|
||||
- name: "Dock: Do not show recent apps"
|
||||
osx_defaults:
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export POW_DST_PORT=88
|
||||
export HOME=~
|
||||
export PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:/usr/local/bin:$PATH"
|
||||
export PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:/usr/local/bin:/opt/homebrew/bin:$PATH"
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
const homedir = require('os').homedir();
|
||||
const fs = require("fs");
|
||||
|
||||
function voltaPrettierSearchDirs(voltaDir) {
|
||||
const packagesDir = `${voltaDir}/tools/image/packages`;
|
||||
|
||||
let paths = []
|
||||
let parents = [];
|
||||
|
||||
fs.readdirSync(packagesDir).forEach((item) => {
|
||||
if (/^prettier-plugin-[^/]+$/.test(item)) {
|
||||
paths.push(`${packagesDir}/${item}/lib`);
|
||||
}
|
||||
|
||||
if (item == '@prettier') {
|
||||
paths = paths.concat(
|
||||
findDirs(`${packagesDir}/@prettier`, /^plugin-[^/]+$/, "lib")
|
||||
);
|
||||
} else if (/^@[^/]+$/.test(item)) {
|
||||
parents.push(`${packagesDir}/${item}`);
|
||||
}
|
||||
|
||||
return [];
|
||||
})
|
||||
|
||||
parents.forEach((parent) => {
|
||||
paths = paths.concat(findDirs(parent, /^prettier-plugin-[^/]+$/, "lib"));
|
||||
})
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
function findDirs(parent, pattern, suffix) {
|
||||
return fs.readdirSync(parent).flatMap((item) => {
|
||||
const fp = `${parent}/${item}`;
|
||||
if (pattern.test(item) && fs.statSync(fp).isDirectory()) {
|
||||
if (suffix) {
|
||||
return `${fp}/${suffix}`;
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
return [];
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
pluginSearchDirs: voltaPrettierSearchDirs(`${homedir}/.volta`),
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user