Something went wrong. Try again.
jujutsu file annotations for neovim (like blame)
Something went wrong. Try again.
3.0 kB · 85 lines
Lua
at master
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586local util = require("jjannotate.util")
local M = {}
---@class jjannotate.Range---@field start integer 0-indexed inclusive---@field _end integer 0-indexed inclusive
---@class jjannotate.Line---@field range jjannotate.Range---@field change_id string---@field author string---@field timestamp string
---@class jjannotate.AnnotateResult---@field lines jjannotate.Line[]---@field longest_timestamp integer---@field row_index jjannotate.Line[]---@field change_id_index table<string, jjannotate.Line[]>
--- A version control backend. Every backend annotation resolves a `revision`--- to a canonical revision ID and annotates/reads files at it.---@class jjannotate.Backend---@field name string backend name, e.g. "jj" or "git"---@field marker string root marker used to detect the backend, e.g. ".jj" or ".git"---@field annotate fun(repo: string, path: string, revision: string, cb: fun(result: jjannotate.AnnotateResult?))---@field show fun(repo: string, revision: string)---@field file_contents fun(repo: string, path: string, revision: string, cb: fun(contents: string?))---@field resolve_revision fun(repo: string, revision: string?, cb?: fun(id: string?)): string?
---@class jjannotate.RepoInfo---@field backend jjannotate.Backend---@field repo string repo root---@field path string path within `repo`
--- Backends in detection priority order.---@type jjannotate.Backend[]M.backends = { require("jjannotate.backend.jj"), require("jjannotate.backend.git") }
--- Resolves the given `path`'s backend, repo root, and relative path within the repo.--- Returns `nil` if `path` is not in any supported repo.---@param path string---@return jjannotate.RepoInfo?function M.path_info(path) if path == "" then return nil end
path = vim.fs.normalize(vim.fs.abspath(path))
for _, backend in ipairs(M.backends) do local repo = vim.fs.root(path, backend.marker) if repo then local relpath = vim.fs.relpath(repo, path) if relpath then return { backend = backend, repo = repo, path = relpath } end end endend
--- Resolves the given `buf`'s backend, repo root, and relative path within the repo.--- Handles annotate URI buffers, falling back to filesystem detection.--- Returns `nil` if the buffer is not in any supported repo.---@param buf integer---@return jjannotate.RepoInfo?function M.buf_info(buf) local ref = util.parse_uri("annotate", vim.api.nvim_buf_get_name(buf)) if ref then local info = M.path_info(ref.repo) if info then return { backend = info.backend, repo = ref.repo, path = ref.path } end end
return M.path_info(vim.api.nvim_buf_get_name(buf))end
--- Detects the backend for the given path (or repo root).---@param path string---@return jjannotate.Backend?function M.detect(path) local info = M.path_info(path) if not info then util.notify(string.format("`%s` is not in a jj or git repo", path), vim.log.levels.ERROR) return end return info.backendend
return M