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-06 22:17:17-07:00
logab4ae993dcea0f05f4a2236a79370096be97debf
tree4030737a374d95e68be7619d0e1799a4ba3cbc69
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, 190 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+184-1
......@@ -81,7 +81,190 @@ 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 format_short_commit_header(commit) ++ "\n" ++
162 format_commit_description(commit)
163 )
164 '';
165
166 "format_commit_description(commit)" = ''
167 label("desc", format_commit_firstline(commit.description().first_line())) ++
168 "\n" ++ if(
169 commit.description().starts_with("WIP:") || commit.current_working_copy(),
170 commit.description().remove_prefix(commit.description().first_line()).remove_prefix("\n").trim_end() ++ "\n ",
171 if(commit.description().remove_prefix(commit.description().first_line()).trim().len() > 0,
172 label("muted", lines_collapsed(commit.description().lines().filter(|x| x.trim().len() > 0).len() - 1)),
173 " "
174 )
175 )
176 '';
177 "lines_collapsed(count)" =
178 ''("[" ++ stringify(count ++ " line" ++ if(count == 1, "", "s")) ++ " collapsed]\n")'';
179 "format_commit_firstline(line)" = ''
180 if(line.starts_with("WIP:"),
181 label("cc_wip", " WIP ") ++ " " ++ format_commit_firstline_a_wip(line.remove_prefix("WIP:").trim()),
182 format_commit_firstline_a_wip(line)
183 )
184 '';
185 "format_commit_firstline_a_wip(line)" = ''
186 if(line.starts_with("feat:") || line.starts_with("feat("),
187 label("cc_feat", "feat") ++ format_commit_firstline_a_cc_type(line.remove_prefix("feat")),
188 if(line.starts_with("fix:") || line.starts_with("fix("),
189 label("cc_fix", "fix") ++ format_commit_firstline_a_cc_type(line.remove_prefix("fix")),
190 if(line.starts_with("hotfix:") || line.starts_with("hotfix("),
191 label("cc_hotfix", "hotfix") ++ format_commit_firstline_a_cc_type(line.remove_prefix("hotfix")),
192 if(line.starts_with("chore:") || line.starts_with("chore("),
193 label("cc_chore", "chore") ++ format_commit_firstline_a_cc_type(line.remove_prefix("chore")),
194 if(line.starts_with("test:") || line.starts_with("test("),
195 label("cc_other", "test") ++ format_commit_firstline_a_cc_type(line.remove_prefix("test")),
196 if(line.starts_with("refactor:") || line.starts_with("refactor("),
197 label("cc_other", "refactor") ++ format_commit_firstline_a_cc_type(line.remove_prefix("refactor")),
198 if(line.starts_with("perf:") || line.starts_with("perf("),
199 label("cc_other", "perf") ++ format_commit_firstline_a_cc_type(line.remove_prefix("perf")),
200 if(line.starts_with("lib:") || line.starts_with("lib("),
201 label("cc_other", "lib") ++ format_commit_firstline_a_cc_type(line.remove_prefix("lib")),
202 label("cc_header", line)
203 ))))))))
204 '';
205 "format_commit_firstline_a_cc_type(rest)" = ''
206 if(rest.starts_with("(") && rest.contains(")"),
207 format_firstline_cc_scope(rest, index_of_close_paren(rest)),
208 format_firstline_a_cc(rest))
209 '';
210 "format_firstline_cc_scope(rest, index)" = ''
211 label("cc_scope", rest.substr(0, index)) ++ format_firstline_a_cc(rest.substr(index, rest.len()))
212 '';
213 "format_firstline_a_cc(rest)" = ''
214 if(rest.starts_with(":"),
215 label("muted", ":") ++ label("cc_header", rest.remove_prefix(":")),
216 label("cc_header", rest)
217 )
218 '';
219 # sorry!
220 "index_of_close_paren(line)" = ''
221 stringify(if(line.substr(1, 2) == ")", "A",
222 if(line.substr(2, 3) == ")", "AA",
223 if(line.substr(3, 4) == ")", "AAA",
224 if(line.substr(4, 5) == ")", "AAAA",
225 if(line.substr(5, 6) == ")", "AAAAA",
226 if(line.substr(6, 7) == ")", "AAAAAA",
227 if(line.substr(7, 8) == ")", "AAAAAAA",
228 if(line.substr(8, 9) == ")", "AAAAAAAA",
229 if(line.substr(9, 10) == ")","AAAAAAAAA",
230 if(line.substr(10, 11) == ")", "AAAAAAAAAA",
231 if(line.substr(11, 12) == ")", "AAAAAAAAAAA",
232 if(line.substr(12, 13) == ")", "AAAAAAAAAAAA",
233 if(line.substr(13, 14) == ")", "AAAAAAAAAAAAA",
234 if(line.substr(14, 15) == ")", "AAAAAAAAAAAAAA",
235 if(line.substr(15, 16) == ")", "AAAAAAAAAAAAAAA",
236 if(line.substr(16, 17) == ")", "AAAAAAAAAAAAAAAA",
237 if(line.substr(17, 18) == ")", "AAAAAAAAAAAAAAAAA",
238 if(line.substr(18, 19) == ")", "AAAAAAAAAAAAAAAAAA",
239 if(line.substr(19, 20) == ")", "AAAAAAAAAAAAAAAAAAA",
240 if(line.substr(20, 21) == ")", "AAAAAAAAAAAAAAAAAAAA",
241 "AAAAAAAAAAAAAAAAAAAAA"
242 ))))))))))))))))))))).len() + 1
243 '';
244
245 "format_short_signature(signature)" = "signature.name()";
246 "format_timestamp(timestamp)" = "timestamp.ago()";
247 "format_short_commit_header(commit)" = ''
248 separate(" ",
249 if(commit.current_working_copy(), label("active_marker", " ACTIVE ")),
250 if(commit.conflict(), label("conflict_marker", " CONFLICT ")),
251 format_short_change_id_with_hidden_and_divergent_info(commit),
252 format_short_signature(commit.author()),
253 label("muted", "|"),
254 if(commit.description().trim().len() > 0, label("muted", format_timestamp(commit_timestamp(commit)))),
255 commit.bookmarks(),
256 commit.tags(),
257 commit.working_copies(),
258 label("muted", "(") ++
259 format_short_commit_id(commit.commit_id()) ++
260 label("muted", ")"),
261 if(config("ui.show-cryptographic-signatures").as_boolean(),
262 format_short_cryptographic_signature(commit.signature())),
263 )
264 '';
265 };
266 };
267 };
85268
86269 ssh = {
87270 enable = true;