Closed hqkhan closed 6 months ago
I could add an option, for example (something like this):
require("gitlinker").setup({
filename_formatter = function(bufnr, git_root_dir)
local bufname = vim.api.nvim_buf_get_name(bufnr)
local rel_filename = get relative path of `bufname` based on `git_root_dir`
return rel_filename
end
})
By default, the filename_formatter
will always returns the current buffer's relative path. Which is exactly what we have now.
But for your use case, you can overwrite the default configs with:
--- @param src The string value
--- @param target The `target` string to be found
--- @return integer? The `target` string index been found in `src`
local function string_find(src, target)
...
end
require("gitlinker").setup({
filename_formatter = function(bufnr)
local bufname = vim.api.nvim_buf_get_name(bufnr)
local filename_end_pos = string_find(bufname, '[')
if type(filename_end_pos) == 'number' and filename_end_pos > 0 then
return string.sub(bufname, 1, filename_end_pos-1)
else
-- for other cases, still use the old method
local rel_filename = get relative path of `bufname` based on `git_root_dir`
return rel_filename
end
end
})
Does that look good for your use case?
Hi @linrongbin16 . Thank you for such a quick response!
That does look good to me for this case! To confirm this will still be running git cat-file -e <commit_hash_of_head>:<file_name>
even though the current buffer is checking out changes from a different commit hash. That said, the file is expected to exist by definition of bcommit so we should be good there.
oh......., It seems cannot use the commit ID from fzf-lua's bcommit result, unless we add 1 more parameter (for example) rev
to allow user input a customize commit ID to overwrite the auto detected.
Based on current naming style of this plugin, I will name them:
file
: a customized file path, that allow user to overwrite the default file path. By default it's nil
, so this plugin will auto generate the relative file path based on current buffer's information (bufnr
, etc).rev
: a customized commit ID, that allow user to overwrite the default commit ID. By default it's nil
, so this plugin will auto generate the commit ID based on current git repository's information.Note: these 2 parameters will be add to both user command GitLink
and the API require("gitlinker").link
.
So you can use with either:
:GitLink file=xxx rev=xxx
require("gitlinker").link({file="xxx", rev="xxx"})
Once done, you should be able to define a key mapping like this:
--- @param s The string value to be find
--- @param c The target string to find
--- @return integer? The first index of target `c` been found in `s`, return `nil` if not found
local function string_find(s, c)
-- implement find function
end
local function file_on_bcommit()
local bufnr = vim.api.nvim_get_current_buf()
local bufname = vim.api.nvim_buf_get_name()
local first_left_bracket_pos = string_find(bufname, '[')
if type(first_left_bracket_pos) == 'number' and first_left_bracket_pos > 0 then
local relpath = string.sub(bufname, 1, first_left_bracket_pos-1)
return relpath
end
-- return nil, this plugin will use the default generated file path
return nil
end
local function rev_on_bcommit()
local bufnr = vim.api.nvim_get_current_buf()
local bufname = vim.api.nvim_buf_get_name()
local first_left_bracket_pos = string_find(bufname, '[')
if type(first_left_bracket_pos) == 'number' and first_left_bracket_pos > 0 then
local rev = string.sub(bufname, first_left_bracket_pos+1, string.len(bufname)-1)
return rev
end
-- return nil, so this plugin will use the default generated commit ID
return nil
end
vim.keymap.set(
{"n", 'v'},
"<leader>gF",
function()
require("gitlinker").link({
file = file_on_bcommit(),
rev = rev_on_bcommit(),
})
end,
{ silent = true, noremap = true, desc = "GitLink on fzf-lua bcommit" }
)
Oo this is interesting. I think that should work. I think I'll also wrap GitLink
command with my own command. My own command will simply look at the buffer path to see if it's of bcommit
. If it is, then it'll call gitlinker.link
underneath or simply continue on to call GitLink
the normal way.
That way, there's only one keybind I need to remember and it should work for both cases.
hi @hqkhan ,
New feature is merged into master, have a try!
You can use something like :GitLink! file=lua/gitlinker.lua
, and :GitLink! blame rev=839215b
.
Awesome! Ty! Will be trying soon and I'll post back here with results :D
Hi @linrongbin16. I may be missing something but the path checker is still causing issues.
2024-04-24 04:05:29,369436 [@/home/hqkhan/.local/share/nvim/lazy/gitlinker.nvim/lua/gitlinker/git.lua:48] DEBUG: |_run_cmd| args:{ "git", "cat-file", "-e", "94d726ea019be2b6b59e2a9f42fc90010a36209b:.editorconfig[7ac8301]" }, cwd:"/local/home/hqkhan/Sources/nvim/gitlinker.nvim"
2024-04-24 04:05:29,374767 [@/home/hqkhan/.local/share/nvim/lazy/gitlinker.nvim/lua/gitlinker/git.lua:63] DEBUG: |_run_cmd| result:{
stderr = { "fatal: path '.editorconfig[7ac8301]' does not exist in '94d726ea019be2b6b59e2a9f42fc90010a36209b'" },
stdout = {},
<metatable> = <1>{
__index = <table 1>,
has_err = <function 1>,
has_out = <function 2>,
new = <function 3>,
print_err = <function 4>
}
}
2024-04-24 04:05:29,375184 [@/home/hqkhan/.local/share/nvim/lazy/gitlinker.nvim/lua/gitlinker/git.lua:37] ERROR: fatal: path '.editorconfig[7ac8301]' does not exist in '94d726ea019be2b6b59e2a9f42fc90010a36209b'
In the case of rev
being provided, shouldn't gitlink be checking if the file path exists in that rev instead of checking where it's currently at?
it looks like my implementation forgot to skip these checkings.
I may fix these.
Update: I fixed this issue in #240 , @hqkhan would you please take a look?
Hi @linrongbin16. It's working! I just need to parse the file name better but other than that, it looks good from GitLinker's side as far as I can tell.
Wanted to post my final working solution that I've tested.
local function string_find(s, c)
return string.find(s, c)
end
local function get_git_filename(filename)
local output = vim.fn.system { 'git', 'ls-files', '--full-name', filename }
if output == "" then
return nil
end
output = output:gsub("\n", "")
return output
end
local function file_on_bcommit()
local bufnr = vim.api.nvim_get_current_buf()
local bufname = vim.api.nvim_buf_get_name(bufnr)
local first_left_bracket_pos = string_find(bufname, "%[")
if type(first_left_bracket_pos) == 'number' and first_left_bracket_pos > 1 then
local relpath = string.sub(bufname, 1, first_left_bracket_pos - 1)
local git_path = get_git_filename(relpath)
-- Make sure it returned something, otherwise let's return nil so gitlinker can do default stuff
return git_path
end
-- return nil, this plugin will use the default generated file path
return nil
end
local function rev_on_bcommit()
local bufnr = vim.api.nvim_get_current_buf()
local bufname = vim.api.nvim_buf_get_name(bufnr)
local first_left_bracket_pos = string_find(bufname, "%[")
if type(first_left_bracket_pos) == 'number' and first_left_bracket_pos > 1 then
local rev = string.sub(bufname, first_left_bracket_pos + 1, string.len(bufname) - 1)
return rev
end
-- return nil, so this plugin will use the default generated commit ID
return nil
end
local function has_value(tab, val)
for _, value in ipairs(tab) do
if value == val then
return true
end
end
return false
end
local function get_remote()
local output = vim.fn.system { 'git', 'remote' }
local remotes = {}
if output ~= nil then
for s in output:gmatch("[^\r\n]+") do
table.insert(remotes, s)
end
end
if #remotes == 0 or not has_value(remotes, "origin") then
return nil
end
return "origin"
end
return {
"linrongbin16/gitlinker.nvim",
cmd = "GitLink",
opts = {},
keys = {
{
"<leader>gy",
function()
require("gitlinker").link({
file = file_on_bcommit(),
rev = rev_on_bcommit(),
remote = get_remote(),
})
end,
mode = { "n", "v" },
desc = "Yank git link or fzf-lua bcommit"
},
},
config = function(opts)
opts = opts or {}
opts.debug = true
opts.file_log = true
opts.router = {
browse = {
["^git.**"] = your_router
},
}
require "gitlinker".setup(opts)
end
}
Might have some rough edges that I'll find out about later on but overall, it's working nicely. Thanks again for your help :)
Details
This is more about asking for guidance on how I can make gitlinker work with fzf-lua's
bcommit
. Withbcommit
, I can open a file in a new buffer at the selected commit. This newly created buffer has the following naming format:<file_name>[commit_hash]
. Example:editorconfig[7ac8301]
.This doesn't work currently as we don't move commits or change branches from wherever we're at. It simply opens a new buffer with changes from that commit.
Now, if gitlinker went through all the checks auto-magically and put me in my router function, I can do a check to see if the name follows the naming format described above and create my URL accordingly. However, we run into an error that the file (newly created buffer) doesn't exist in the commit which makes sense. I've provided my config and error message below from log file.
I wanted to ask if there's a way for me to bypass this check of
git cat-file -e <commit_hash>:<file_name>
. The rest of the info gathering git calls can remain as I've already specified a remote in my keybind (see below). If I can get to my router function, I should be able to get it to work.Config
Error