Home

Awesome

🫵 blame.nvim

blame.nvim is a fugitive.vim style git blame visualizer for Neovim.

Window: <img width="1499" alt="window_blame_cut" src="https://github.com/FabijanZulj/blame.nvim/assets/38249221/68669b29-923e-48ee-9c75-39b096e98ede">

Virtual: <img width="1489" alt="virtual_blame_cut" src="https://github.com/FabijanZulj/blame.nvim/assets/38249221/ea70061c-09a4-45d9-9eec-41881646ae25">

Same commits are highlighted in the same color

Installation

return {
  {
    "FabijanZulj/blame.nvim",
    lazy = false,
    config = function()
      require('blame').setup {}
    end,
  },
}

Activating additional blame options

return {
  {
    "FabijanZulj/blame.nvim",
    lazy = false,
    config = function()
      require('blame').setup {}
    end,
    opts = {
      blame_options = { '-w' },
    },
  },
}

Usage

The following commands are used:

There are two built-in views:

Configuration

Default config:

{
    date_format = "%d.%m.%Y",
    virtual_style = "right_align",
    views = {
        window = window_view,
        virtual = virtual_view,
        default = window_view,
    },
    focus_blame = true,
    merge_consecutive = false,
    max_summary_width = 30,
    colors = nil,
    blame_options = nil,
    commit_detail_view = "vsplit",
    format_fn = formats.commit_date_author_fn,
    mappings = {
        commit_info = "i",
        stack_push = "<TAB>",
        stack_pop = "<BS>",
        show_commit = "<CR>",
        close = { "<esc>", "q" },
    }
}

These are the fields you can configure by passing them to the require('blame').setup({}) function:

Features

Blame stack

You can see the state of the file prior to selected commit using stack_push(default: <TAB>) and stack_pop (default: <BS>) mappings. In the pop-up on the right the stack is shown and you can go back and forward through the history of the file.

<details open> <summary>Details</summary>

https://github.com/FabijanZulj/blame.nvim/assets/38249221/f91bf22b-7bbe-4cdb-acac-f1c7fc993aab

</details>

Commit info

To see the full commit info pop-up press the commit_info(default: 'i') mapping on the specific commit line. (press i again to move into the popup window, or move cursor to close the popup)

<details open> <summary>Details</summary> <img width="1495" alt="commit_info_popup" src="https://github.com/FabijanZulj/blame.nvim/assets/38249221/3ece577d-3e40-457c-9457-5ccce58f94ff"> </details>

Full commit info

To see the full commit data press the show_commit(default <CR>) mapping on the commit line

<details open> <summary>Details</summary> <img width="1495" alt="commit_info_full" src="https://github.com/FabijanZulj/blame.nvim/assets/38249221/84aad831-0c0d-44fe-a38f-6a4d027070c3"> </details>

Advanced

Custom format function

You can provide custom format functions that get executed for every blame line and are shown in a view. By default highlight is created for each commit hash so it can be used in hl field.

Signature of the function:

FormatFn fun(line_porcelain: Porcelain, config:Config, idx:integer):LineWithHl

where LineWithHl is:

---@class LineWithHl
---@field idx integer
---@field values {textValue: string, hl: string}[]
---@field format string

And Porcelain being:

---@class Porcelain
---@field author string
---@field author_email string
---@field author_time number
---@field author_tz string
---@field committer string
---@field committer_mail string
---@field committer_time number
---@field committer_tz string
---@field filename string
---@field hash string
---@field previous string
---@field summary string
---@field content string

Built in format functions are:

("blame.formats.default_formats").date_message

("blame.formats.default_formats").commit_date_author_fn

Your function must return a list of values ({textValue: string, hl: string}). Those text fragments will be formatted with provided format field and highlighted with the HiglightGroup given in hl

for more info check the implementations for 'date_message' or 'commit_date_author_fn'

Custom views

It is also possible to implement your custom view. To implement a custom view you need to implement this interface:

---@class BlameView
---@field new fun(self, config: Config) : BlameView
---@field open fun(self, lines: Porcelain[])
---@field is_open fun(): boolean
---@field close fun(cleanup: boolean)

And add it to the config field table views See 'blame.views.window_view' and 'blame.views.virtual_view' for examples

Events

These user events are emitted

So you can do something like this: there are some conflicts with some winbar plugins, in this case barbecue is toggled

vim.api.nvim_create_autocmd("User", {
    pattern = "BlameViewOpened",
    callback = function(event)
        local blame_type = event.data
        if blame_type == "window" then
            require("barbecue.ui").toggle(false)
        end
    end,
})

vim.api.nvim_create_autocmd("User", {
    pattern = "BlameViewClosed",
    callback = function(event)
        local blame_type = event.data
        if blame_type == "window" then
            require("barbecue.ui").toggle(true)
        end
    end,
})