git 日志图中特定提交的突出显示行

Highlight line for specific commit in git log graph

我试图在我的 git 日志图中突出显示特定提交的整行。我之前创建了一个 git 日志别名来格式化我的日志输出。我试图使用我的别名突出显示包含提交 ID 的特定行。

别名 ~/.gitconfig

# Base command for log formatting
lg-base = "log --graph --decorate=short --decorate-refs-exclude='refs/tags/*' --color=always"
# Version 1 log format
lg1 = !"git lg-base --format=format:'%C(#f0890c)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(#d10000)%d%C(reset)'"

通过搜索 6 months 进行测试只是因为它应该表现相同并且可能更好地展示我的问题。

git lg1 | grep --color=always -E '(6 months).*|$'

匹配正确的行。但它并没有突出显示右边的整行,当试图突出显示该行的左侧部分时,它也没有按预期工作。可能是因为我不太会用regex。

git lg1 | grep --color=always -E '.*(6 months).*|$'

而是在开头标记 *

如果您有其他方法,我也可以,只要我可以使用我的格式化 git 日志别名即可。

是这里问题的关键:尽管 grep 添加自己的 颜色(或颜色)更改转义序列以突出显示该行, Git 已经加入了变色指令。每个这样的指令,对于其中一种命名的颜色,看起来像这样:

ESC[number

其中 number 部分是前景色的 30 到 37 和背景色的 40 到 47(加上一些额外的粗体或暗色代码,我不会包括在这里)。 (%C(reset) 发送 ESC [ m 并且您的橙色选择器使用 24 位颜色指令,与可追溯到 1990 年代的八种基色相比,它的支持范围更小)。因此,原始输出为:

* <sp> <orange> <hash-ID> <reset> <sp> - <sp> <blue> (n months ago) <reset> ...

grep 在匹配的表达式周围添加了红色,即 ESC [ 31 m 和一个重置 — 但 表达式中的现有转义符仍然存在。

到目前为止,避免这一切的最简单方法是完全停止使用颜色转义序列,这样 grep 添加的转义序列就会像 sore 红拇指一样突出。当然,这违背了您的目标,即在 突出显示的行中保留 color-changing 转义符。但是你还没有解释你想用 color-changing 行或部分行的转义来做什么, 突出显示。回答这个问题将决定下一步做什么。

有多种方法可以解决这个问题。例如,您可以使用 %x1b(name-of-color)%<directive>%x1b(reset) 代替 %C(color)%<directive>%C(reset) 来插入文字序列 ESC ( 颜色名称或重置)假设 有问题的终端将使用以小写 m 字符结尾的 ANSI 样式转义,并尝试编写sed 或 awk 中的一些东西(我会用 awk 来处理这么复杂的东西,只是因为它不太像写行噪音)进行匹配——awk 支持正则表达式匹配——如果找到,去掉 来自 matched 部分的颜色序列并添加自己的颜色序列。 Post-process 这与插入适当的 terminal-dependent color-change 序列的东西有关,或者保留原始 ESC [ ... m 序列,假设你在 window 中使用该形式,您将获得所需的输出(如果需要,您现在可以通过 less -R 进行管道传输)。

一个可以执行您想要的操作的框架 awk 程序是:

/<desired regex>/ { handle matched line; next; }
{ print }

困难的部分是“处理匹配的行”。 GNU awk 有 RSTART 和 RLENGTH 可以提供很多帮助;参见,例如 this answer。行首到RSTART-1的子串不匹配(这可能为空),RSTART+RLENGTH到行尾的子串(也可能为空)也不匹配; [=21=] 在 RSTART 的子字符串长度 RLENGTH 匹配,如果你想在整个过程中应用你的基本红色(或其他),你可以在这里删除任何 color-changing 序列。


示例脚本(作者:Robin Hellmers)

创建脚本并将其放置在您喜欢的位置,例如

~/.local/bin/highlight-commit.awk

内容

#!/usr/bin/nawk -f

BEGIN {
    n = split(commits,arrayCommits," ");
    background="145;0;0"
    foreground="255;255;255"
}
{
    # Compare with every given input e.g. commit id
    for (i=1; i <= n; i++) {
        if(match([=13=],arrayCommits[i])) {
            # Remove any ANSI color escape sequence for matching row
            gsub("\x1b\[[0-9;]*m","",[=13=])
            # Create ANSI color escape sequence for whole row
            [=13=] = sprintf("\x1b[48;2;%sm\x1b[38;2;%sm%s\x1b[0m\x1b[0m", 
                         background,
                         foreground,
                         [=13=]);
            break;
        }
    }
    printf("%s\n", [=13=]);
}

~/.gitconfig中添加如下alias:

[alias]
    highlight-commit = "!f() { git lg | awk -v commits=\"$*\" -f ~/.local/bin/highlight-commit.awk | less -XR; }; f"

通过调用例如两次提交:

git highlight-commit 82451f8 310fca4