authorgravatar for git@paperclover.netclover caruso <git@paperclover.net> 2025-09-01 12:37:58-07:00
committergravatar for git@paperclover.netclover caruso <git@paperclover.net> 2025-09-24 11:49:54-07:00
logf4817e31485e763cdf2dad6b021895f964033aba
treed0a744e67ff3a94ffb8d15ed414289578156d970
parent617dc280cb05d0d59c1e936d93e2d7bbe97cab65
signature Signed by SSH key SHA256:xbd+BjjhyBfwk7GVoURf9Yx0gzDerHbvYv7SddNWmAs

clover: configure jujutsu log to look really nice

so far, part of my strategy has been tagging incomplete commits with "WIP" and then renaming them once i'm ready to push them. here, the default log revset will just show all WIPs, and the custom display template will very clearly highlight them along with the usual conventional commit stuff.

2 files changed, 192 insertions(+), 1 deletions(-)

modules/home/default.nix+6
......@@ -152,6 +152,12 @@ in
152152 };
153153 ui = {
154154 default-command = "log";
155 diff-formatter = [
156 "${pkgs.difftastic}/bin/difft"
157 "--color=always"
158 "$left"
159 "$right"
160 ];
155161 pager = "${pkgs.bat}/bin/bat --style=plain";
156162 };
157163 };
users/clover/home.nix+186-1
......@@ -81,7 +81,192 @@ in
8181 # use a git-specific email
8282 git.userEmail = "git@paperclover.net";
8383
84 jujutsu.enable = true;
84 jujutsu = {
85 enable = true;
86 # my workflow is based on creating changes and editing them. while they
87 # are in progress the description starts with "WIP: "
88 settings = rec {
89 colors = {
90 bookmark = "green";
91 bookmarks = colors.bookmark;
92 local_bookmarks = colors.bookmarks;
93 remote_bookmarks = colors.bookmark;
94 "working_copy bookmark" = "bright green";
95 "working_copy bookmarks" = colors."working_copy bookmark";
96 "working_copy local_bookmarks" = colors."working_copy bookmark";
97 "working_copy remote_bookmarks" = colors."working_copy bookmark";
98
99 "author" = {
100 fg = "white";
101 bold = false;
102 italic = true;
103 };
104 "working_copy author" = colors.author;
105
106 desc = {
107 bold = false;
108 fg = "bright white";
109 };
110 description = colors.desc;
111 cc_wip = {
112 fg = "bright yellow";
113 bold = true;
114 reverse = true;
115 };
116 cc_header = {
117 bold = true;
118 fg = "bright white";
119 };
120 cc_feat = "green";
121 cc_fix = "red";
122 cc_hotfix = "red";
123 cc_chore = "yellow";
124 cc_test = "blue";
125 cc_other = "blue";
126 cc_scope = {
127 fg = "cyan";
128 bold = false;
129 italic = true;
130 };
131
132 active_marker = {
133 fg = "bright magenta";
134 bold = true;
135 reverse = true;
136 };
137 conflict_marker = {
138 fg = "bright red";
139 bold = true;
140 reverse = true;
141 };
142
143 timestamp = "bright black";
144 commit_id = {
145 fg = "bright black";
146 bold = false;
147 };
148 muted = "bright black";
149 };
150 # ui.graph.style = "square";
151 revsets = {
152 log = "ancestors(description(regex:\"^(WIP:|\\\\s*$)\"), 3) | ancestors(immutable_heads(), 2) | ancestors(visible_heads(), 2)";
153 short-prefixes = "(trunk()..@)::";
154 };
155 templates.log = "hl_wip(self)";
156
157 template-aliases = {
158 # log template, highlighting the WIP commits by making everything else faded out
159 "hl_wip(commit)" = ''
160 if(commit.root(), format_root_commit(commit),
161 label("__commit__",
162 format_short_commit_header(commit) ++ "\n" ++
163 format_commit_description(commit)
164 )
165 )
166 '';
167
168 "format_commit_description(commit)" = ''
169 label("desc", format_commit_firstline(commit.description().first_line())) ++
170 "\n" ++ if(
171 commit.description().starts_with("WIP:") || commit.current_working_copy(),
172 commit.description().remove_prefix(commit.description().first_line()).remove_prefix("\n").trim_end() ++ "\n ",
173 if(commit.description().remove_prefix(commit.description().first_line()).trim().len() > 0,
174 label("muted", lines_collapsed(commit.description().lines().filter(|x| x.trim().len() > 0).len() - 1)),
175 " "
176 )
177 )
178 '';
179 "lines_collapsed(count)" =
180 ''("[" ++ stringify(count ++ " line" ++ if(count == 1, "", "s")) ++ " collapsed]\n")'';
181 "format_commit_firstline(line)" = ''
182 if(line.starts_with("WIP:"),
183 label("cc_wip", " WIP ") ++ " " ++ format_commit_firstline_a_wip(line.remove_prefix("WIP:").trim()),
184 format_commit_firstline_a_wip(line)
185 )
186 '';
187 "format_commit_firstline_a_wip(line)" = ''
188 if(line.starts_with("feat:") || line.starts_with("feat("),
189 label("cc_feat", "feat") ++ format_commit_firstline_a_cc_type(line.remove_prefix("feat")),
190 if(line.starts_with("fix:") || line.starts_with("fix("),
191 label("cc_fix", "fix") ++ format_commit_firstline_a_cc_type(line.remove_prefix("fix")),
192 if(line.starts_with("hotfix:") || line.starts_with("hotfix("),
193 label("cc_hotfix", "hotfix") ++ format_commit_firstline_a_cc_type(line.remove_prefix("hotfix")),
194 if(line.starts_with("chore:") || line.starts_with("chore("),
195 label("cc_chore", "chore") ++ format_commit_firstline_a_cc_type(line.remove_prefix("chore")),
196 if(line.starts_with("test:") || line.starts_with("test("),
197 label("cc_other", "test") ++ format_commit_firstline_a_cc_type(line.remove_prefix("test")),
198 if(line.starts_with("refactor:") || line.starts_with("refactor("),
199 label("cc_other", "refactor") ++ format_commit_firstline_a_cc_type(line.remove_prefix("refactor")),
200 if(line.starts_with("perf:") || line.starts_with("perf("),
201 label("cc_other", "perf") ++ format_commit_firstline_a_cc_type(line.remove_prefix("perf")),
202 if(line.starts_with("lib:") || line.starts_with("lib("),
203 label("cc_other", "lib") ++ format_commit_firstline_a_cc_type(line.remove_prefix("lib")),
204 label("cc_header", line)
205 ))))))))
206 '';
207 "format_commit_firstline_a_cc_type(rest)" = ''
208 if(rest.starts_with("(") && rest.contains(")"),
209 format_firstline_cc_scope(rest, index_of_close_paren(rest)),
210 format_firstline_a_cc(rest))
211 '';
212 "format_firstline_cc_scope(rest, index)" = ''
213 label("cc_scope", rest.substr(0, index)) ++ format_firstline_a_cc(rest.substr(index, rest.len()))
214 '';
215 "format_firstline_a_cc(rest)" = ''
216 if(rest.starts_with(":"),
217 label("muted", ":") ++ label("cc_header", rest.remove_prefix(":")),
218 label("cc_header", rest)
219 )
220 '';
221 # sorry!
222 "index_of_close_paren(line)" = ''
223 stringify(if(line.substr(1, 2) == ")", "A",
224 if(line.substr(2, 3) == ")", "AA",
225 if(line.substr(3, 4) == ")", "AAA",
226 if(line.substr(4, 5) == ")", "AAAA",
227 if(line.substr(5, 6) == ")", "AAAAA",
228 if(line.substr(6, 7) == ")", "AAAAAA",
229 if(line.substr(7, 8) == ")", "AAAAAAA",
230 if(line.substr(8, 9) == ")", "AAAAAAAA",
231 if(line.substr(9, 10) == ")","AAAAAAAAA",
232 if(line.substr(10, 11) == ")", "AAAAAAAAAA",
233 if(line.substr(11, 12) == ")", "AAAAAAAAAAA",
234 if(line.substr(12, 13) == ")", "AAAAAAAAAAAA",
235 if(line.substr(13, 14) == ")", "AAAAAAAAAAAAA",
236 if(line.substr(14, 15) == ")", "AAAAAAAAAAAAAA",
237 if(line.substr(15, 16) == ")", "AAAAAAAAAAAAAAA",
238 if(line.substr(16, 17) == ")", "AAAAAAAAAAAAAAAA",
239 if(line.substr(17, 18) == ")", "AAAAAAAAAAAAAAAAA",
240 if(line.substr(18, 19) == ")", "AAAAAAAAAAAAAAAAAA",
241 if(line.substr(19, 20) == ")", "AAAAAAAAAAAAAAAAAAA",
242 if(line.substr(20, 21) == ")", "AAAAAAAAAAAAAAAAAAAA",
243 "AAAAAAAAAAAAAAAAAAAAA"
244 ))))))))))))))))))))).len() + 1
245 '';
246
247 "format_short_signature(signature)" = "signature.name()";
248 "format_timestamp(timestamp)" = "timestamp.ago()";
249 "format_short_commit_header(commit)" = ''
250 separate(" ",
251 if(commit.current_working_copy(), label("active_marker", " ACTIVE ")),
252 if(commit.conflict(), label("conflict_marker", " CONFLICT ")),
253 format_short_change_id_with_hidden_and_divergent_info(commit),
254 format_short_signature(commit.author()),
255 label("muted", "|"),
256 if(commit.description().trim().len() > 0, label("muted", format_timestamp(commit_timestamp(commit)))),
257 commit.bookmarks(),
258 commit.tags(),
259 commit.working_copies(),
260 label("muted", "(") ++
261 format_short_commit_id(commit.commit_id()) ++
262 label("muted", ")"),
263 if(config("ui.show-cryptographic-signatures").as_boolean(),
264 format_short_cryptographic_signature(commit.signature())),
265 )
266 '';
267 };
268 };
269 };
85270
86271 ssh = {
87272 enable = true;