vibe coding 了一个 blame-reveal 包,Fringe 彩色显示 Git Blame

用我改的这个也可以吧。@LuciusChen已经把lazy loading、显示这些都做得很好了,我改成了我喜欢的显示风格。

最近在重构,搞得更好扩展一些,才把 overlay统一管理了,颜色也抽出来统一了,下一步状态机整理下,现在太混乱了。

1 个赞

创建和销毁overlay这个事情还是闪,对我来说是。也许能有其他方式解决吧,但是我没找到比较好的方式。

能把我在left margin显示commit message的功能加上去吗?

另外必须要设为nil,显示所有的commit,如果不显示所有的commit,有时候会出现移动光标时,显示的commit message文字叠加的情况。上面有图就是这个问题。

显示bitmap时,只有一个字符的宽度,叠加也看不出来,但是显示文字就很明显看出问题。

(setq blame-reveal-recent-days-limit nil)

等我重构完看看

重构了之后,比较大的一些改动如下。

  1. 统一的 overlay 管理
  2. 统一的 header 格式化(用户有感知,这方面自定义需要自定义函数了,更加灵活。)
  3. 颜色管理采用策略,方便扩展。
  4. 增加 lazy loading 动画(很丝滑)
  5. 分模块,并增加测试工具。
  6. 增加 trailing 形式显示 commit msg (用户有感知)
1 个赞

我在你重构之后又改了一下

可以的,我还在想咋做,还是想统一逻辑。

我认为统一逻辑什么的可以搁置。要考虑这个项目面临的俩问题。

首先是面对time git blame --porcelain bigfile >/dev/null 的时间。这个异步应该可以解决,打开文件放动画。

第二个问题还是这个时间,你修改文件后要执行git blame吗?我这里说的是没保存的时候和保存时候,你是不是还要在执行一遍 git blame?如果写一句保存一下就光放动画了。

仅是我做类似项目中得到的经验之谈。Idea上有先天优势,vscode的插件gitlens,你可以去体验,编辑就关闭blame,也得根据实际情况做妥协,要想清楚要什么啊。

没懂你什么意思,动画那个是大文件才有的。而且为什么会开着blame修改代码?

换了个口味,左边的commit message文字的颜色改成随机生成的颜色,这样可视性和区分度更好。

你试试我做的这个。 :joy:,因为我就这么尝试干了一个。纯纯是因为自己做的时候一点想法,没准你也遇得到 :joy:,当然你可能并不是想做类似的事情。

借鉴加了 global-mode,其他不打算加啦,算是开发告一段落了。这个包的核心还是 fringe(也是当初写这个包的出发点,这一点不能变。),其他的 margin block 以及 inline 都是信息展示的一种方式,和 fringe 的显示逻辑保持一致。

在之前的基础上做了 recursive blame 的增强,见第一个动图。另外做了 move/copy 模式,也就是可以查看到来自在其他文件时的修改,见第二个动图。

比如我创建了一个项目,有一些 git 操作。

#!/bin/bash
# Git Blame 插件测试脚本

# 跨平台 sed 函数
sed_inplace() {
    if sed --version >/dev/null 2>&1; then
        sed -i "$@"
    else
        sed -i '' "$@"
    fi
}

# 1. 初始化仓库
mkdir -p git-blame-test
cd git-blame-test
git init

# 2. 创建初始文件
cat > original.txt << 'EOF'
Line 1: Initial content by Alice
Line 2: More content by Alice
Line 3: Even more content
Line 4: Last line by Alice
EOF
git add original.txt
git commit -m "Initial commit by Alice" --author="Alice <[email protected]>"

# 3. Bob 修改部分内容
sed_inplace '3s/.*/Line 3: Modified by Bob/' original.txt
git add original.txt
git commit -m "Bob modifies line 3" --author="Bob <[email protected]>"

# 4. 重命名文件
git mv original.txt renamed.txt
git commit -m "Rename original.txt to renamed.txt"

# 5. Charlie 添加新行
cat >> renamed.txt << 'EOF'
Line 5: Added by Charlie
EOF
git add renamed.txt
git commit -m "Charlie adds line 5" --author="Charlie <[email protected]>"

# 6. 复制文件
cp renamed.txt copy1.txt
git add copy1.txt
git commit -m "Create copy1.txt from renamed.txt"

# 7. David 修改复制的文件
sed_inplace '2s/.*/Line 2: Modified in copy by David/' copy1.txt
git add copy1.txt
git commit -m "David modifies copy1.txt" --author="David <[email protected]>"

# 8. 移动到子目录
mkdir -p subdir
git mv renamed.txt subdir/moved.txt
git commit -m "Move renamed.txt to subdir/"

# 9. Eve 在移动后的文件中修改
sed_inplace '1s/.*/Line 1: Modified after move by Eve/' subdir/moved.txt
git add subdir/moved.txt
git commit -m "Eve modifies moved file" --author="Eve <[email protected]>"

# 10. 部分复制
head -n 2 subdir/moved.txt > partial.txt
echo "Line 3: New content by Frank" >> partial.txt
git add partial.txt
git commit -m "Frank creates partial copy" --author="Frank <[email protected]>"

# 11. 重命名后再修改
git mv copy1.txt final.txt
sed_inplace '4s/.*/Line 4: Modified after rename by Grace/' final.txt
git add final.txt
git commit -m "Rename and modify by Grace" --author="Grace <[email protected]>"

我们来看 moved.txt 的操作记录。

第1行: Alice创建 → [重命名/移动] → Eve修改 ✏️ → 递归到 Alice(boundary) ⛔
       ↑                            ↑              ↑
       original.txt                 moved.txt      停止,不追踪 original.txt
       (显示在 filename)            (最后修改)      (已经是 initial commit)

第2行: Alice创建 ⛔ (从未修改,boundary,显示 filename: original.txt)
       ↑
       停止,已经是 initial commit

第3行: Alice创建 → Bob修改 ✏️ → [重命名/移动] → 递归到 Alice(boundary) ⛔
       ↑           ↑                              ↑
       original    original.txt                   停止
       (能追踪到)  (最后修改位置)

第4行: Alice创建 ⛔ (从未修改,boundary,显示 filename: original.txt)
       ↑
       停止

第5行: [重命名] → Charlie添加 ➕ → [移动] → 递归到重命名提交(第5行不存在) ⛔
                  ↑                        ↑
                  renamed.txt              停止,这行是新增的
                  (能追踪到)

所以按照这个来说,第三行和第五行的修改是来自于 moved.txt 之前的文件。

1

上面的演示是 recursive blame 的时候,直接根据 git 信息中的 previous filename 来溯源的。(这里需要在第一行向后递归后回到该文件的第一个 commit,下面的行才会从 git 信息中获取到 previous filename,因此最直接的方法还是下面开启 M/C 模式。)

2

上面的演示是直接开启 M/C 模式之后,可以直接看到溯源的信息,也就是修改来自于之前的哪个文件。

1 个赞

请问原来blame-reveal-show-commit-details函数的major mde是special-mode的,为什么改成view-mode了。能不能改回special-mode。view-mode打开的buffer的major mode是fundamental-mode,用evil的话,默认evil-mode,没法直接按q键退出了。

可以的,晚上改。

1 个赞