My new new dotfiles :3
1# based on https://github.com/vic/vix/blob/den/modules/vic/jujutsu.nix
2# + A bunch of nice stuff from yandros
3{ ... }:
4{
5 flake-file.inputs.jjui.url = "github:idursun/jjui";
6 flake-file.inputs.jjui.inputs.nixpkgs.follows = "nixpkgs";
7 flake-file.inputs.jjui.inputs.flake-parts.follows = "flake-parts";
8
9 my.programs.provides.jj.homeManager =
10 { pkgs, inputs', ... }:
11 let
12 jjui = inputs'.jjui.packages.jjui;
13 in
14 {
15 home.packages = [
16 pkgs.lazyjj
17 pkgs.jj-fzf
18 pkgs.meld
19 jjui
20 ];
21
22 programs.jujutsu =
23 let
24 diff-formatter = [
25 (pkgs.lib.getExe pkgs.difftastic)
26 "--color=always"
27 "$left"
28 "$right"
29 ];
30 in
31 {
32 enable = true;
33
34 settings = {
35 user.name = "Suya Singh";
36 user.email = "suya1671@tuta.io";
37
38 revsets.log = "default()";
39
40 revset-aliases = {
41 "trunk()" = "main@origin";
42
43 # commits on working-copy compared to `trunk`
44 "compared_to_trunk()" = "(trunk()..@):: | (trunk()..@)-";
45
46 # immutable heads:
47 # main and not mine commits.
48 "immutable_heads()" = "trunk() | (trunk().. & ~mine())";
49 # "immutable_heads()" = "builtin_immutable_heads() | remote_bookmarks()";
50
51 "closest_bookmark(to)" = "heads(::to & bookmarks())";
52
53 # jjui default
54 "default_log()" = "present(@) | ancestors(immutable_heads().., 2) | present(trunk())";
55
56 "default()" = "coalesce(trunk(),root())::present(@) | ancestors(visible_heads() & recent(), 2)";
57
58 "recent()" = "committer_date(after:'1 week ago')";
59 };
60
61 template-aliases = {
62 "format_short_signature(signature)" = "signature.email()";
63 "format_timestamp(timestamp)" = "timestamp.ago()";
64 };
65
66 ui = {
67 default-command = [
68 "log"
69 "--stat"
70 "--template"
71 "builtin_log_compact_full_description"
72 "--limit"
73 "3"
74 ];
75 inherit diff-formatter;
76 # TODO: make this based on whatever the active editor is
77 editor = "zeditor --wait";
78 diff-editor = "meld-3";
79 merge-editor = "meld";
80 conflict-marker-style = "git";
81 movement.edit = false;
82 show-cryptographic-signatures = true;
83 };
84
85 signing = {
86 behaviour = "drop";
87 backend = "gpg";
88 # TODO: make this configurable
89 key = "suya1671@tuta.io";
90 };
91
92 git.sign-on-push = true;
93
94 templates = {
95 git_push_bookmark = "suya/jj-change-";
96
97 log_node = ''
98 coalesce(
99 if(!self, label("elided", "~")),
100 separate("",
101 surround(" 📍 Workspace: ", " 📍\n", label("working_copy", self.working_copies())),
102 label(
103 separate(" ",
104 if(current_working_copy, "working_copy"),
105 if(immutable, "immutable"),
106 if(conflict, "conflict"),
107 ),
108 coalesce(
109 if(current_working_copy, "🫵"),
110 if(hidden, "☁️"),
111 if(immutable, "🛡️"),
112 if(conflict, "💥"),
113 " ○",
114 ),
115 ),
116 )
117 )
118 '';
119
120 log = ''
121 if(root,
122 format_root_commit(self),
123 label(
124 if(self.current_working_copy(), "working_copy"),
125 concat(
126 separate("\n ",
127 separate(" ",
128 separate(" ",
129 if(!self.hidden(), self.change_id().shortest(6)),
130 if(self.hidden(), label("hidden", "hidden")),
131 if(self.divergent(), label("divergent", "??")),
132 ),
133 self.commit_id().shortest(6),
134 if(self.hidden(),
135 label("hidden", surround("(", ")",
136 self.change_id().shortest(6),
137 )),
138 ),
139 if(self.empty(), label("empty",
140 if(self.description(),
141 "[EMPTY]",
142 if(current_working_copy,
143 "[CLEAN WORKING DIR]",
144 "[PLACEHOLDER]",
145 ),
146 ),
147 )),
148 if(self.description(),
149 self.description().first_line(),
150 separate(" ",
151 if(!self.empty(), label("empty", "🚧 [staged changes]")),
152 ),
153 ),
154 if(false, label("author",
155 if(mine,
156 "me",
157 if(
158 author.name().contains(" "),
159 separate("",
160 author.name().substr(0, 1),
161 ".",
162 author.name().match(regex:"( [^\\s]*)+"),
163 ),
164 author.name(),
165 ),
166 ),
167 )),
168 if(true, label("author",
169 if(mine,
170 "me",
171 author.name().match(regex:"[^\\s]* .|.*"),
172 ),
173 )),
174 ),
175 surround("↖ ", "", separate(" ",
176 surround("🔖 ", "", separate(" ",
177 self.bookmarks(),
178 self.tags(),
179 )),
180 self.working_copies(),
181 if(self.git_head(), label("git_head", "git checkout")),
182 if(self.conflict(), label("conflict", "CONFLICT")),
183 if(config("ui.show-cryptographic-signatures").as_boolean(),
184 format_short_cryptographic_signature(signature)),
185
186 )),
187 ) ++ "\n",
188 ),
189 )
190 )
191 '';
192 };
193
194 aliases = {
195 # shut up and just SEND IT
196 force = [
197 "--config"
198 "revset-aliases.'immutable_heads()'='builtin_immutable_heads()'"
199 ];
200
201 tug = [
202 "bookmark"
203 "move"
204 "--from"
205 "closest_bookmark(@-)"
206 "--to"
207 "@-"
208 ];
209
210 lr = [
211 "log"
212 "-r"
213 "default() & recent()"
214 ];
215
216 s = [ "show" ];
217
218 # This way you can do smth like --to $(jj resolve-changeid 'heads(bookmarks() & trunk()..@)'
219 resolve-changeid = [
220 "log"
221 "--color=auto"
222 "--no-graph"
223 "-T"
224 ''change_id.short() ++ "\n"''
225 "-r"
226 ];
227
228 resolve-commitid = [
229 "log"
230 "--color=auto"
231 "--no-graph"
232 "-T"
233 ''commit_id.short() ++ "\n"''
234 "-r"
235 ];
236
237 sq = [
238 "squash"
239 "-i"
240 ];
241
242 sU = [
243 "squash"
244 "-i"
245 "-f"
246 "@+"
247 "-t"
248 "@"
249 ];
250
251 su = [
252 "squash"
253 "-i"
254 "-f"
255 "@"
256 "-t"
257 "@+"
258 ];
259
260 sd = [
261 "squash"
262 "-i"
263 "-f"
264 "@"
265 "-t"
266 "@-"
267 ];
268
269 sD = [
270 "squash"
271 "-i"
272 "-f"
273 "@-"
274 "-t"
275 "@"
276 ];
277
278 l = [
279 "log"
280 "-r"
281 "compared_to_trunk()"
282 "--config"
283 "template-aliases.'format_short_id(id)'='id.shortest().upper()'"
284 "--config"
285 "template-aliases.'format_short_change_id(id)'='id.shortest().upper()'"
286 "--config"
287 "template-aliases.'format_timestamp(timestamp)'='timestamp.ago()'"
288 ];
289
290 # like git log, all visible commits in the repo
291 ll = [
292 "log"
293 "-r"
294 ".."
295 ];
296
297 extract = [
298 "bash"
299 ''
300 set -x
301 jj create -B @
302 jj squash -i -r @ "$@"
303 jj describe @-
304 ''
305 ""
306 ];
307
308 rawbash = [
309 "util"
310 "exec"
311 "--"
312 "bash"
313 "-c"
314 ];
315
316 op-last-id = [
317 "op"
318 "log"
319 "--no-graph"
320 "-n1"
321 "-T"
322 "id.short(12)"
323 ];
324
325 checkpoint = [
326 "rawbash"
327 ''
328 echo "Checkpoint! To restore:" >&2
329 echo " jj op restore $(jj op-last-id --color always)" >&2
330 ''
331 ""
332 ];
333
334 bash = [
335 "rawbash"
336 ''
337 if [ -z "$\{JJ_REENTRANT:-}" ]; then
338 jj checkpoint
339 JJ_CHECKPOINT_ID="$(jj op-last-id --color never)"
340 jj_rollback() (
341 echo '[jj] Operation failed; automatically rolling back to last checkpoint.' >&2
342 set -x
343 jj op restore "$\{JJ_CHECKPOINT_ID}"
344 )
345 trap 'jj_rollback' SIGINT SIGTERM
346 fi
347 script="$\{1?}"
348 shift
349 JJ_REENTRANT=1 jj rawbash "set -euo pipefail; $\{script}" "$@" || jj_rollback
350 ''
351 ""
352 ];
353 };
354
355 };
356 };
357
358 home.file.".config/jjui/config.toml".source =
359 let
360 # https://github.com/idursun/jjui/wiki/Configuration
361 toml = {
362 leader.e.help = "Edit file";
363 leader.e.send = [
364 "$"
365 "jj edit $change_id && $VISUAL $file"
366 "enter"
367 ];
368 };
369 fmt = pkgs.formats.toml { };
370 in
371 fmt.generate "config.toml" toml;
372 };
373}