From ab4ae993dcea0f05f4a2236a79370096be97debf Mon Sep 17 00:00:00 2001 From: clover caruso Date: Mon, 1 Sep 2025 12:37:58 -0700 Subject: [PATCH] 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. --- modules/home/default.nix | 6 ++ users/clover/home.nix | 185 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 190 insertions(+), 1 deletion(-) diff --git a/modules/home/default.nix b/modules/home/default.nix index 38811b880fb60af75ae564d2ba787a1a7c7f2dd7..64fbd631b34421db740a329ea8f752b863bf684d 100644 --- a/modules/home/default.nix +++ b/modules/home/default.nix @@ -152,6 +152,12 @@ in }; ui = { default-command = "log"; + diff-formatter = [ + "${pkgs.difftastic}/bin/difft" + "--color=always" + "$left" + "$right" + ]; pager = "${pkgs.bat}/bin/bat --style=plain"; }; }; diff --git a/users/clover/home.nix b/users/clover/home.nix index de5840b081b97253c5991ee78fac02dba651a767..363ad183b149b7a8458c18ac2840542d48f3782e 100644 --- a/users/clover/home.nix +++ b/users/clover/home.nix @@ -81,7 +81,190 @@ in # use a git-specific email git.userEmail = "git@paperclover.net"; - jujutsu.enable = true; + jujutsu = { + enable = true; + # my workflow is based on creating changes and editing them. while they + # are in progress the description starts with "WIP: " + settings = rec { + colors = { + bookmark = "green"; + bookmarks = colors.bookmark; + local_bookmarks = colors.bookmarks; + remote_bookmarks = colors.bookmark; + "working_copy bookmark" = "bright green"; + "working_copy bookmarks" = colors."working_copy bookmark"; + "working_copy local_bookmarks" = colors."working_copy bookmark"; + "working_copy remote_bookmarks" = colors."working_copy bookmark"; + + "author" = { + fg = "white"; + bold = false; + italic = true; + }; + "working_copy author" = colors.author; + + desc = { + bold = false; + fg = "bright white"; + }; + description = colors.desc; + cc_wip = { + fg = "bright yellow"; + bold = true; + reverse = true; + }; + cc_header = { + bold = true; + fg = "bright white"; + }; + cc_feat = "green"; + cc_fix = "red"; + cc_hotfix = "red"; + cc_chore = "yellow"; + cc_test = "blue"; + cc_other = "blue"; + cc_scope = { + fg = "cyan"; + bold = false; + italic = true; + }; + + active_marker = { + fg = "bright magenta"; + bold = true; + reverse = true; + }; + conflict_marker = { + fg = "bright red"; + bold = true; + reverse = true; + }; + + timestamp = "bright black"; + commit_id = { + fg = "bright black"; + bold = false; + }; + muted = "bright black"; + }; + ui.graph.style = "square"; + revsets = { + log = "ancestors(description(regex:\"^(WIP:|\\\\s*$)\"), 3) | ancestors(immutable_heads(), 2) | ancestors(visible_heads(), 2)"; + short-prefixes = "(trunk()..@)::"; + }; + templates.log = "hl_wip(self)"; + + template-aliases = { + # log template, highlighting the WIP commits by making everything else faded out + "hl_wip(commit)" = '' + if(commit.root(), format_root_commit(commit), + format_short_commit_header(commit) ++ "\n" ++ + format_commit_description(commit) + ) + ''; + + "format_commit_description(commit)" = '' + label("desc", format_commit_firstline(commit.description().first_line())) ++ + "\n" ++ if( + commit.description().starts_with("WIP:") || commit.current_working_copy(), + commit.description().remove_prefix(commit.description().first_line()).remove_prefix("\n").trim_end() ++ "\n ", + if(commit.description().remove_prefix(commit.description().first_line()).trim().len() > 0, + label("muted", lines_collapsed(commit.description().lines().filter(|x| x.trim().len() > 0).len() - 1)), + " " + ) + ) + ''; + "lines_collapsed(count)" = + ''("[" ++ stringify(count ++ " line" ++ if(count == 1, "", "s")) ++ " collapsed]\n")''; + "format_commit_firstline(line)" = '' + if(line.starts_with("WIP:"), + label("cc_wip", " WIP ") ++ " " ++ format_commit_firstline_a_wip(line.remove_prefix("WIP:").trim()), + format_commit_firstline_a_wip(line) + ) + ''; + "format_commit_firstline_a_wip(line)" = '' + if(line.starts_with("feat:") || line.starts_with("feat("), + label("cc_feat", "feat") ++ format_commit_firstline_a_cc_type(line.remove_prefix("feat")), + if(line.starts_with("fix:") || line.starts_with("fix("), + label("cc_fix", "fix") ++ format_commit_firstline_a_cc_type(line.remove_prefix("fix")), + if(line.starts_with("hotfix:") || line.starts_with("hotfix("), + label("cc_hotfix", "hotfix") ++ format_commit_firstline_a_cc_type(line.remove_prefix("hotfix")), + if(line.starts_with("chore:") || line.starts_with("chore("), + label("cc_chore", "chore") ++ format_commit_firstline_a_cc_type(line.remove_prefix("chore")), + if(line.starts_with("test:") || line.starts_with("test("), + label("cc_other", "test") ++ format_commit_firstline_a_cc_type(line.remove_prefix("test")), + if(line.starts_with("refactor:") || line.starts_with("refactor("), + label("cc_other", "refactor") ++ format_commit_firstline_a_cc_type(line.remove_prefix("refactor")), + if(line.starts_with("perf:") || line.starts_with("perf("), + label("cc_other", "perf") ++ format_commit_firstline_a_cc_type(line.remove_prefix("perf")), + if(line.starts_with("lib:") || line.starts_with("lib("), + label("cc_other", "lib") ++ format_commit_firstline_a_cc_type(line.remove_prefix("lib")), + label("cc_header", line) + )))))))) + ''; + "format_commit_firstline_a_cc_type(rest)" = '' + if(rest.starts_with("(") && rest.contains(")"), + format_firstline_cc_scope(rest, index_of_close_paren(rest)), + format_firstline_a_cc(rest)) + ''; + "format_firstline_cc_scope(rest, index)" = '' + label("cc_scope", rest.substr(0, index)) ++ format_firstline_a_cc(rest.substr(index, rest.len())) + ''; + "format_firstline_a_cc(rest)" = '' + if(rest.starts_with(":"), + label("muted", ":") ++ label("cc_header", rest.remove_prefix(":")), + label("cc_header", rest) + ) + ''; + # sorry! + "index_of_close_paren(line)" = '' + stringify(if(line.substr(1, 2) == ")", "A", + if(line.substr(2, 3) == ")", "AA", + if(line.substr(3, 4) == ")", "AAA", + if(line.substr(4, 5) == ")", "AAAA", + if(line.substr(5, 6) == ")", "AAAAA", + if(line.substr(6, 7) == ")", "AAAAAA", + if(line.substr(7, 8) == ")", "AAAAAAA", + if(line.substr(8, 9) == ")", "AAAAAAAA", + if(line.substr(9, 10) == ")","AAAAAAAAA", + if(line.substr(10, 11) == ")", "AAAAAAAAAA", + if(line.substr(11, 12) == ")", "AAAAAAAAAAA", + if(line.substr(12, 13) == ")", "AAAAAAAAAAAA", + if(line.substr(13, 14) == ")", "AAAAAAAAAAAAA", + if(line.substr(14, 15) == ")", "AAAAAAAAAAAAAA", + if(line.substr(15, 16) == ")", "AAAAAAAAAAAAAAA", + if(line.substr(16, 17) == ")", "AAAAAAAAAAAAAAAA", + if(line.substr(17, 18) == ")", "AAAAAAAAAAAAAAAAA", + if(line.substr(18, 19) == ")", "AAAAAAAAAAAAAAAAAA", + if(line.substr(19, 20) == ")", "AAAAAAAAAAAAAAAAAAA", + if(line.substr(20, 21) == ")", "AAAAAAAAAAAAAAAAAAAA", + "AAAAAAAAAAAAAAAAAAAAA" + ))))))))))))))))))))).len() + 1 + ''; + + "format_short_signature(signature)" = "signature.name()"; + "format_timestamp(timestamp)" = "timestamp.ago()"; + "format_short_commit_header(commit)" = '' + separate(" ", + if(commit.current_working_copy(), label("active_marker", " ACTIVE ")), + if(commit.conflict(), label("conflict_marker", " CONFLICT ")), + format_short_change_id_with_hidden_and_divergent_info(commit), + format_short_signature(commit.author()), + label("muted", "|"), + if(commit.description().trim().len() > 0, label("muted", format_timestamp(commit_timestamp(commit)))), + commit.bookmarks(), + commit.tags(), + commit.working_copies(), + label("muted", "(") ++ + format_short_commit_id(commit.commit_id()) ++ + label("muted", ")"), + if(config("ui.show-cryptographic-signatures").as_boolean(), + format_short_cryptographic_signature(commit.signature())), + ) + ''; + }; + }; + }; ssh = { enable = true; -- 2.54.0