···11+What if you could view code review comments in your editor
22+as LSP diagnostics?
33+44+Requirements:
55+66+- The forge to support a format like [f3](https://f3.forgefriends.org/)
77+- Users can write reviews in the browser
88+99+More technically:
1010+1111+- The "LSP" would expect the forge to support a format like [f3](https://f3.forgefriends.org/)
1212+- Your editor will sync review comments from your codeforge
1313+- Your LSP should know when to show these diagnostics
1414+ * in branch-based review, reviews are not really attached
1515+ to anything, but based on current git branch perhaps?
1616+ * in commit-based review, reviews can be attached to a
1717+ change-id (a la jujutsu), and displayed based on current
1818+ working copy change-id
1919+2020+Cons:
2121+2222+- How do you reply to these? Is there a way to introduce
2323+ bidirectional communication?
2424+- Review comments are not always on code, they could be on
2525+ commit message or just general architecture, for which an
2626+ "inbox" is a better abstraction
2727+- Bidirectional communication eventually becomes a chat app
2828+2929+This thought was inspired by recent comments on
3030+"offline-first" reviews by [matklad]()
+364
posts/configuring_jujutsu.md
···11+There are a lot of reasons to use jujutsu, but this post is
22+not about that. I have this terrible habit of turning every
33+knob on a tool before I even fully absorb how it works; and
44+boy does `jj` have a lot of knobs.
55+66+### Templates
77+88+`jj` let you tweak nearly every single character of its
99+output. In fact, `jj` includes a full-blown templating
1010+language to do so. Lets start from the basics:
1111+1212+Format all timestamps in relative fashion, like "5 hours
1313+ago":
1414+1515+```toml
1616+[template-aliases]
1717+"format_timestamp(timestamp)" = "timestamp.ago()";
1818+```
1919+2020+The default nodes in the log graph are a bit large for my
2121+taste, we can modify the `log_node` template to fix that:
2222+2323+```toml
2424+[templates]
2525+log_node = '''
2626+ label("node",
2727+ coalesce(
2828+ if(!self, label("elided", "~")),
2929+ if(current_working_copy, label("working_copy", "@")),
3030+ if(conflict, label("conflict", "×")),
3131+ if(immutable, label("immutable", "*")),
3232+ label("normal", "·")
3333+ )
3434+ )
3535+'''
3636+```
3737+3838+This uses smaller iconography in `jj log` (these icons are
3939+also more widely available in fonts, in my experience):
4040+4141+```
4242+@ wuuownsw me@oppi.li 21 minutes ago 30d1bd12
4343+│ (no description set)
4444+· plmznxvy me@oppi.li 5 hours ago push-plmznxvyqrqw git_head() 051c142e
4545+│ appview: pulls: bump sourceRev for stacks without causing resubmits
4646+│ * towvwqxk x@icyphox.sh 4 hours ago master a588f625
4747+│ │ appview: pages/markup: don't double camo in post process
4848+│ * ryzqnyvs me@oppi.li 4 hours ago ea4b520a
4949+│ │ appview: fix stack merging
5050+│ * kqvutzxr me@oppi.li 4 hours ago ff73ca23
5151+├─╯ appview: rework RepoLanguages
5252+* vwpqwmms jeynesbrook@gmail.com 8 hours ago d759587b
5353+│ appview: repo: inject language percentage into repo index
5454+~
5555+```
5656+5757+Much nicer! And speaking of `log`, I find it hard to parse
5858+the output when every change occupies two lines instead of
5959+just one line, we can remedy that quickly; in fact, `jj` has
6060+a builtin template for single-line log outputs:
6161+6262+```
6363+λ jj log -T builtin_log_oneline
6464+@ wuuownsw me@oppi.li 22 minutes ago 30d1bd12 (no description set)
6565+· plmznxvy me@oppi.li 5 hours ago push-plmznxvyqrqw git_head() 051c142e appview: pulls: bump sourceRev for stacks without causing resubmits
6666+│ * towvwqxk x@icyphox.sh 4 hours ago master a588f625 appview: pages/markup: don't double camo in post process
6767+│ * ryzqnyvs me@oppi.li 4 hours ago ea4b520a appview: fix stack merging
6868+│ * kqvutzxr me@oppi.li 4 hours ago ff73ca23 appview: rework RepoLanguages
6969+├─╯
7070+* vwpqwmms jeynesbrook 8 hours ago d759587b appview: repo: inject language percentage into repo index
7171+│
7272+~
7373+```
7474+7575+Bit too long! I personally do not always need author and
7676+time information when quickly scrolling through the log, so
7777+I created my own template based on `builtin_log_oneline`:
7878+7979+```toml
8080+[templates]
8181+log = '''
8282+ if(root,
8383+ format_root_commit(self),
8484+ label(if(current_working_copy, "working_copy"),
8585+ concat(
8686+ separate(" ",
8787+ format_short_change_id_with_hidden_and_divergent_info(self),
8888+ if(empty, label("empty", "(empty)")),
8989+ if(description,
9090+ description.first_line(),
9191+ label(if(empty, "empty"), description_placeholder),
9292+ ),
9393+ bookmarks,
9494+ tags,
9595+ working_copies,
9696+ if(git_head, label("git_head", "HEAD")),
9797+ if(conflict, label("conflict", "conflict")),
9898+ if(config("ui.show-cryptographic-signatures").as_boolean(),
9999+ format_short_cryptographic_signature(signature)),
100100+ ) ++ "\n",
101101+ ),
102102+ )
103103+ )
104104+'''
105105+```
106106+107107+Which produces:
108108+109109+```
110110+@ wuuownsw (no description set)
111111+· plmznxvy appview: pulls: bump sourceRev for stacks without causing resubmits push-plmznxvyqrqw HEAD
112112+│ * towvwqxk appview: pages/markup: don't double camo in post process master
113113+│ * ryzqnyvs appview: fix stack merging
114114+│ * kqvutzxr appview: rework RepoLanguages
115115+├─╯
116116+* vwpqwmms appview: repo: inject language percentage into repo index
117117+│
118118+~
119119+```
120120+121121+Sweet! To get a more detailed log, you can always use a
122122+different template for the output: `jj log -T
123123+builtin_log_detailed`.
124124+125125+With git, I set `commit.verbose` to true, this lets me view
126126+the diff when composing a commit messaege in my `$EDITOR`:
127127+128128+```bash
129129+λ git commit
130130+# no message passed, opens $EDITOR to compose message
131131+132132+# -- inside vim --
133133+134134+# Please enter the commit message for your changes. Lines starting
135135+# with '#' will be ignored, and an empty message aborts the commit.
136136+#
137137+# On branch trunk
138138+# Changes to be committed:
139139+# new file: scripts/handle.js
140140+#
141141+# ------------------------ >8 ------------------------
142142+# Do not modify or remove the line above.
143143+# Everything below it will be ignored.
144144+diff --git a/scripts/handle.js b/scripts/handle.js
145145+new file mode 100644
146146+index 0000000..d8a07f3
147147+--- /dev/null
148148++++ b/scripts/handle.js
149149+@@ -0,0 +1,104 @@
150150++// Run using node handle.js
151151++// Install axios using npm install axios
152152++// nodejs v18+
153153++const axios = require("axios");
154154+.
155155+.
156156+.
157157+```
158158+159159+The equivalent in `jj` requires modifying the
160160+`draft_commit_description` template:
161161+162162+```toml
163163+[templates]
164164+draft_commit_description ='''
165165+ concat(
166166+ coalesce(description, default_commit_description, "\n"),
167167+ surround(
168168+ "\nJJ: This commit contains the following changes:\n", "",
169169+ indent("JJ: ", diff.stat(72)),
170170+ ),
171171+ "\nJJ: ignore-rest\n",
172172+ diff.git(),
173173+ )
174174+'''
175175+```
176176+177177+### Revsets
178178+179179+As a not-so-power-user, I presently only use revsets to
180180+improve my `jj log` experience. In the context of `jj log`,
181181+giving it a revset means "here is a bag of revisions, graph
182182+them for me neatly".
183183+184184+I find myself using the "rebase" flow quite often:
185185+186186+- I hack on a stack of changes
187187+- `trunk` is updated by my fellow collaborators
188188+- I rebase my stack using `jj rebase -s <mine> -d <trunk>`
189189+190190+And I scrub through the log output to roughly figure out how
191191+much work it would be to rebase, what I need for this is:
192192+193193+- the changes added to `trunk` since I last diverged from it
194194+- the changes add to my stack since I last diverged from
195195+ `trunk`
196196+197197+```
198198+ X--Y--Z my stack
199199+ /
200200+ F--A--B--C--D trunk
201201+```
202202+203203+If you want `jj log` to print this (and by "this", I mean,
204204+the graph above, exactly as presented), you have to supply
205205+it a `revset` argument that grabs X, Y, Z, A, B, C, D and F.
206206+Some examples of revsets are:
207207+208208+```
209209+@ # the rev marking the working copy
210210+x # the rev identified by shorthand `x`
211211+x | y # the set of two revs, [x, y]
212212+@ | trunk() # the set of two revs, [@, trunk()]
213213+.. # everything in this repository
214214+all() # also everything in this repository
215215+fork_point(@ | trunk()) # the rev where @ and trunk() forked off
216216+```
217217+218218+And the revset that captures "ahead-behind" style output is:
219219+220220+```
221221+trunk()..@ | @..trunk() | trunk() | @:: | fork_point(trunk() | @)
222222+```
223223+224224+Which includes:
225225+226226+- `trunk()..@`: the new changes that my collaborators have added
227227+- `@..trunk()`: the new changes that I have added
228228+- `trunk()`: the trunk rev itself
229229+- `@::`: all descendants of `@`
230230+- `fork_point(trunk() | @)`: the rev from which the two
231231+ streams of work diverged
232232+233233+Rougly, when working on a stack, this is what I can see by
234234+supplying the above revset expression (simplified output):
235235+236236+```bash
237237+λ jj log -r 'trunk()..@ | @..trunk() | trunk() | @:: | fork_point(trunk() | @)'
238238+@ xdihgmke <-- me
239239+· vurstull
240240+· plmznxvy
241241+· ihefghyy
242242+│ * towvwqxk trunk <-- trunk
243243+│ * ryzqnyvs
244244+│ * kqvutzxr
245245+├─╯
246246+* vwpqwmms <-- fork-point
247247+```
248248+249249+And sometimes, when I am editing older parts of my stack
250250+(`@::` helps us grab `xdihgmke` and `vurstull`):
251251+252252+```bash
253253+λ jj log -r 'trunk()..@ | @..trunk() | trunk() | @:: | fork_point(trunk() | @)'
254254+· xdihgmke
255255+· vurstull
256256+@ plmznxvy <-- me
257257+· ihefghyy
258258+│ * towvwqxk trunk <-- trunk
259259+│ * ryzqnyvs
260260+│ * kqvutzxr
261261+├─╯
262262+* vwpqwmms <-- fork-point
263263+```
264264+265265+To rebase, I would run:
266266+267267+```
268268+jj rebase -s ihefghyy -d towvwqxk
269269+```
270270+271271+### Aliases
272272+273273+I imagine that most git power users are already familiar
274274+with aliases. The only alias I see myself using often is:
275275+276276+```toml
277277+[aliases]
278278+tug = ["bookmark" "move" "--from" "heads(::@- & bookmarks())" "--to" "@-"];
279279+```
280280+281281+In action:
282282+283283+```bash
284284+# ugh my bookmark is way behind
285285+λ jj log
286286+@ xdihgmke
287287+· vurstull
288288+· cyzmakil
289289+· plmznxvy
290290+· ihefghyy some-bookmark
291291+│
292292+~
293293+294294+λ jj tug
295295+296296+# ready to push!
297297+λ jj log
298298+@ xdihgmke
299299+· vurstull some-bookmark*
300300+· cyzmakil
301301+· plmznxvy
302302+· ihefghyy
303303+│
304304+~
305305+```
306306+307307+This alias was stolen from this [wonderful
308308+gist](https://gist.github.com/thoughtpolice/8f2fd36ae17cd11b8e7bd93a70e31ad6#file-jjconfig-toml)
309309+by [Austin
310310+Seipp](https://github.com/jj-vcs/jj/blob/main/docs/testimonials.md?plain=1#L120).
311311+312312+### Experimental features
313313+314314+I use one experimental feature, that is only available on
315315+some of the newer versions of jujutsu:
316316+317317+```bash
318318+# built from master
319319+λ jj version
320320+jj 0.29.0-8c7ca30074767257d75e3842581b61e764d022cf
321321+```
322322+323323+```toml
324324+[git]
325325+write-change-id-header = true
326326+```
327327+328328+This writes an extra commit-header (not to be confused with
329329+commit-trailer, which goes directly in the commit body) with
330330+the jujutsu change-id, as seen by inspecting the commit
331331+object:
332332+333333+```bash
334334+λ git cat-file commit 4edebe96159bf81c3be662d0a2b4c7b08a062968
335335+tree a9b7e9e3eed8a22c35829bf586d7560ec8396124
336336+parent edc0d2750d4848bc05cfd3255ee1ca916bea9156
337337+author oppiliappan <me@oppi.li> 1747919102 +0100
338338+committer oppiliappan <me@oppi.li> 1747919102 +0100
339339+change-id skrrxvvxlpzrqzpxlxksvryrykpxkvon <-- this
340340+```
341341+342342+This allows code forges to extract change-ids from commits,
343343+and most crucially: **allows tracking changes across force
344344+pushes**. This enables the [interdiff
345345+format](https://gist.github.com/thoughtpolice/9c45287550a56b2047c6311fbadebed2)
346346+of code-review. Stacking, commit-wise-review, and interdiff
347347+are all supported on [tangled](https://tangled.sh) (you can
348348+read more
349349+[here](https://bsky.app/profile/tangled.sh/post/3lptwcb47kc2u)),
350350+if you submit a branch with this experimental feature
351351+enabled.
352352+353353+### Misc
354354+355355+Couple of other quality of life additions:
356356+357357+```toml
358358+[ui]
359359+default-command = "status"
360360+pager = "delta"
361361+```
362362+363363+I also use nix and home-manager to configure jj, you can
364364+find my configuration [here](https://plonk.li/r/YQ).