Skip to content

Kaiser-Yang/blink-cmp-git

Repository files navigation

blink-cmp-git

Git source for blink.cmp completion plugin. This makes it possible to query pull requests, issues, and users from GitHub or GitLab. This is very useful when you are writing a commit with nvim.

Use # to search for issues and pull requests (! for gitlab's merge requests):

blink-cmp-git pr and issues

Use : to search for commits:

blink-cmp-git commits

Use @ to search for users:

blink-cmp-git pr and issues

Requirements

git is required for default configurations.

gh is required for the github related features.

glab is required for the gitlab related features.

Run checkhealth blink-cmp-git to check the requirements.

Installation

Add the plugin to your packer managers, and make sure it is loaded before blink.cmp.

lazy.nvim

{'saghen/blink.cmp', dependencies={{'Kaiser-Yang/blink-cmp-git', } -- ... other dependencies }, opts={sources={-- add 'git' to the listdefault={'git', 'dictionary', 'lsp', 'path', 'luasnip', 'buffer' }, providers={git={module='blink-cmp-git', name='Git', opts={-- options for the blink-cmp-git }, }, } } } }

Quick Start

git={module='blink-cmp-git', name='Git', -- only enable this source when filetype is gitcommit, markdown, or 'octo'enabled=function() returnvim.tbl_contains({'octo', 'gitcommit', 'markdown' }, vim.bo.filetype) end, --- @module'blink-cmp-git'--- @typeblink-cmp-git.Optionsopts={commit={-- You may want to customize when it should be enabled-- The default will enable this when `git` is found and `cwd` is in a git repository-- enable = function() end-- You may want to change the triggers-- triggers ={':' }, } git_centers={github={-- Those below have the same fields with `commit`-- Those features will be enabled when `git` and `gh` (or `curl`) are found and-- remote contains `github.com`-- issue ={-- get_token = function() return '' end,-- },-- pull_request ={-- get_token = function() return '' end,-- },-- mention ={-- get_token = function() return '' end,-- get_documentation = function(item)-- local default = require('blink-cmp-git.default.github')-- .mention.get_documentation(item)-- default.get_token = function() return '' end-- return default-- end-- } }, gitlab={-- Those below have the same fields with `commit`-- Those features will be enabled when `git` and `glab` (or `curl`) are found and-- remote contains `gitlab.com`-- issue ={-- get_token = function() return '' end,-- },-- NOTE:-- Even for `gitlab`, you should use `pull_request` rather than`merge_request`-- pull_request ={-- get_token = function() return '' end,-- },-- mention ={-- get_token = function() return '' end,-- get_documentation = function(item)-- local default = require('blink-cmp-git.default.gitlab')-- .mention.get_documentation(item)-- default.get_token = function() return '' end-- return default-- end-- } } } } },

The configuration above will enable the blink-cmp-git for blink.cmp and show the items when the file's type is gitcommit or markdown. By default, blink-cmp-git will pre-cache everything when it is created. To enable blink-cmp-git all the time makes it possible to pre-cache when you enter insert mode or other mode you can input (blink.cmp will create sources when you can input something).

Note

The default configuration will use curl when gh or glab is not found.

For github users, if you customize the get_token, you should see those below to know which permissions are required:

For gitlab users, see PAT to know how to get the token.

Note

For octo.nvim users, blink-cmp-git supports it. By default, when you are in a octo file, blink-cmp-git will use the octo's path to get the owner and repo to fetch the items.

Reload Cache

There are many cases that will make the cache invalid. For example, if your cwd is in a repository, later you switch your cwd to another repository, the cache will use the first repository's result. To solve this problem, there is a command to reload the cache: BlinkCmpGitReloadCache. This command will clear the cache.

blink-cmp-git will create a auto command which uses should_reload_cache to determine whether or not to reload cache when entering insert mode. The default should_reload_cache will return true when detecting another git repository from octo or cwd.

Note

The command will be available only when the blink-cmp-git source is created. Usually, the source will be created when it is enabled and you are in some mode you can input.

Default Configuration

See default.lua.

FAQs

How to customize the completion items?

Because all features have same fields, I'll use commit as an example.

The blink-cmp-git will first run command from get_command and get_command_args. The standout of the command will be passed to separate_output. So if you want to customize the completion items, you should be aware of what the output of your command looks like.

In most situations, you just need to customize get_label, get_kind_name, get_insert_text and get_documentation. Before you customize them, you should be aware of what the item looks like. See item to know what them look like. The commit item looks like this below:

commit 0216336d8ff00d7b8c9304b23bcca31cbfcdf2c8 Author: Kaiser-Yang <[email protected]> AuthorDate: Sun Jan 12 14:40:38 2025 +0800 Commit: Kaiser-Yang <[email protected]> CommitDate: Sun Jan 12 14:43:15 2025 +0800 Cache empty documentations 

The default getters for commit:

git_centers={commit={-- use the first 7 hash and the first line of the commit message as the labelget_label=function(item) -- For `octo.nvim` users, the `item` is a tableiftype(item) =='table' thenreturnitem.sha:sub(1, 7) ..'' ..item.commit.message:match('([^\n]*)') endreturnitem:match('commit ([^\n]*)'):sub(1, 7) ..'' ..item:match('\n\n%s*([^\n]*)') end, -- use 'Commit' as the kind nameget_kind_name=function(_) return'Commit'end, -- use the first 7 hash as the insert textget_insert_text=function(item) -- For `octo.nvim` users, the `item` is a tableiftype(item) =='table' thenreturnitem.sha:sub(1, 7) endreturnitem:match('commit ([^\n]*)'):sub(1, 7) end, -- use the whole commit message as the documentationget_documentation=function(item) -- For `octo.nvim` users, the `item` is a tableiftype(item) =='table' thenreturn'commit ' ..item.sha..'\n' ..'Author: ' ..item.commit.author.name..' <' ..item.commit.author.email..'>\n' ..'AuthorDate: ' ..item.commit.author.date..'\n' ..'Commit: ' ..item.commit.committer.name..' <' ..item.commit.committer.email..'>\n' ..'CommitDate: ' ..item.commit.committer.date..'\n' ..item.commit.messageendreturnitem-- or you can use `blink-cmp-git.DocumentationCommand` to get the documentation-- return{-- -- the command to get the documentation-- get_command = '',-- get_command_args ={}-- -- how to resolve the output-- resolve_documentation = function(output) return output end-- }-- or return nil to disable the documentation-- return nilend, } }

Note

kind_name is used by those default options:

  • kind_icons

Therefore, if you customize the kind_name, you should customize them too.

How to customize the error message?

From the version v0.2.0, there is a configuration on_error for all the GCSCompletionOptions. on_error is a function like func(return_value: number, standard_error: string): boolean.

When blink-cmp-git find a non-zero return value or a non-empty standard error, it will call on_error with the return value and the standard error. If on_error returns false, the error will be ignored, which means blink-cmp-git will go on to the next step. When on_error returns true, blink-cmp-git will not go on to the next step. The default on_error is to show the error message and return true.

For example, if you want to disable the error message for commit, you just need to use those below:

commit={on_error=function(_, _) returntrueend }

How to add trailing white spaces?

For example, those below will add a trailing white space for commit:

commit={-- or you can update it to other contents such as '\n'insert_text_trailing='' }

NOTE: If you enable pre-insert, switch between items with spaces may make the completion menu disappear. This may be related with treesitter.

How to customize the highlight?

Suppose the item in your completion list is like this below:

 PR #1 Add a new feature 
Highlight Group NameDescription
BlinkCmpGitKind<kind_name>For
BlinkCmpGitKindIcon<kind_name>For PR
BlinkCmpGitLabel<kind_name>IdFor #1
BlinkCmpGitLabel<kind_name>RestFor Add a new feature

Note

The Id part is got by seperating the label by whitespaces, if you customize the get_label, you may need to customize the label_highlight too. See default.lua to learn how to customize it.

The default <kind_name> are Commit, Issue, PR, MR, and Mention.

Besides, you can also customize different highlight for open, closed, locked and merged pull requests or issues.

By default, blink-cmp-git will only fetch the open pull requests or issues. So you should customize the api parameters to fetch all states. See How to customize the APIs?.

Firstly, you should update the get_kind_name to customize the kind_name:

git_centers={github={pull_request={get_kind_name=function(item) -- openPR, closedPR, mergedPR, draftPR, lockedPRreturnitem.lockedand'lockedPR' oritem.draftand'draftPR' oritem.merged_atand'mergedPR' oritem.state..'PR'end, }, issue={get_kind_name=function(item) -- openIssue, reopenedIssue, completedIssue-- not_plannedIssue, lockedIssue, duplicateIssuereturnitem.lockedand'lockedIssue' or (item.state_reasonoritem.state) ..'Issue'end, }, }, gitlab={pull_request={get_kind_name=function(item) -- openedPR, closedPR, mergedPR, draftPR, lockedPRreturnitem.discussion_lockedand'lockedPR' oritem.draftand'draftPR' oritem.state..'PR'end, }, issue={get_kind_name=function(item) -- openedIssue, closedIssuereturnitem.discussion_lockedand'lockedIssue' oritem.state..'Issue'end, }, } }

Then, you can update the icons for the kind_name:

kind_icons={openPR='', openedPR='', closedPR='', mergedPR='', draftPR='', lockedPR='', openIssue='', openedIssue='', reopenedIssue='', completedIssue='', closedIssue='', not_plannedIssue='', duplicateIssue='', lockedIssue='', }

Here is an example for github-like highlight:

localblink_cmp_kind_name_highlight={Commit={default=false, fg='#a6e3a1' }, Mention={default=false, fg='#a6e3a1' }, openPR={default=false, fg='#a6e3a1' }, openedPR={default=false, fg='#a6e3a1' }, closedPR={default=false, fg='#f38ba8' }, mergedPR={default=false, fg='#cba6f7' }, draftPR={default=false, fg='#9399b2' }, lockedPR={default=false, fg='#f5c2e7' }, openIssue={default=false, fg='#a6e3a1' }, openedIssue={default=false, fg='#a6e3a1' }, reopenedIssue={default=false, fg='#a6e3a1' }, completedIssue={default=false, fg='#cba6f7' }, closedIssue={default=false, fg='#cba6f7' }, not_plannedIssue={default=false, fg='#9399b2' }, duplicateIssue={default=false, fg='#9399b2' }, lockedIssue={default=false, fg='#f5c2e7' }, } forkind_name, hlinpairs(blink_cmp_kind_name_highlight) dovim.api.nvim_set_hl(0, 'BlinkCmpGitKind' ..kind_name, hl) vim.api.nvim_set_hl(0, 'BlinkCmpGitKindIcon' ..kind_name, hl) vim.api.nvim_set_hl(0, 'BlinkCmpGitLabel' ..kind_name..'Id', hl) end

You may also need to update the configure_score_offset, otherwise the default may not work as you expected. There is an example:

localfunctionpr_or_issue_configure_score_offset(items) -- Bonus to make sure items sorted as below:localkeys={-- place `kind_name` here{'openIssue', 'openedIssue', 'reopenedIssue' },{'openPR', 'openedPR' },{'lockedIssue', 'lockedPR' },{'completedIssue' },{'draftPR' },{'mergedPR' },{'closedPR', 'closedIssue', 'not_plannedIssue', 'duplicateIssue' }, } localbonus=999999localbonus_score={} fori=1, #keysdofor_, keyinipairs(keys[i]) dobonus_score[key] =bonus* (#keys-i) endendfori=1, #itemsdolocalbonus_key=items[i].kind_nameifbonus_score[bonus_key] thenitems[i].score_offset=bonus_score[bonus_key] end-- sort by number when having the same bonus scorelocalnumber=items[i].label:match('[#!](%d+)') ifnumberthenifitems[i].score_offset==nilthenitems[i].score_offset=0enditems[i].score_offset=items[i].score_offset+tonumber(number) endendendgit_centers={github={pull_request={configure_score_offset=pr_or_issue_configure_score_offset, }, issue={configure_score_offset=pr_or_issue_configure_score_offset, }, }, gitlab={pull_request={configure_score_offset=pr_or_issue_configure_score_offset, }, issue={configure_score_offset=pr_or_issue_configure_score_offset, }, } }

How to customize for enterprise github or gitlab?

Firstly, you should update the enable for each feature, the default enable will enable the plugin when github.com found for github repository and gitlab.com found for gitlab repository in your remote URLs. I'll give you an example for github's issue:

git_centers={github={issue={enable=function() -- Get the default enable resultlocalenable=require('blink-cmp-git.default.github') .issue .enable() localutils=require('blink-cmp-git.utils') -- Place your enterprise's domain here-- When using `find` without parameters, escape special characters using '%'.-- Escape characters: ( ) . % + - * ? [ ^ $-- `find(pattern, start_index, plain)`-- `start_index = 1` starts searching from the first character.-- `plain = true` ensures an exact match instead of a pattern match.returnenableorutils.get_repo_remote_url():find('enterprise.example.com', 1, true) end, } } }

Then, you should see how to customize the APIs to customize the request domain.

How to customize the APIs?

By default, blink-cmp-git will request those endpoints below:

FeatureAPI Endpoint
github.issuerepos/OWNER/REPO/issues
github.pull_requestrepos/OWNER/REPO/pulls
github.mentionrepos/OWNER/REPO/contributors
github.mention.get_documentationusers/USERNAME
gitlab.issueprojects/PROJECT_ID/issues
gitlab.pull_requestprojects/PROJECT_ID/merge_requests
gitlab.mentionprojects/PROJECT_ID/users
gitlab.mention.get_documentationusers/USERID

You can see github rest API and gitlab rest API to know what the available parameters are.

I'll give you an example for github.issue to customize per_page and sort:

git_centers={github={issue={get_command_args=function(command, token) -- Get the default argslocalargs=require('blink-cmp-git.default.github') .issue .get_command_args(command, token) localutils=require('blink-cmp-git.utils') -- The last element is the API endpoint, customize itifcommand=='curl' then-- You can update the `github.com` to your enterprise's domainargs[#args] ='https://api.github.com/repos/' ..-- NOTE:-- for `gitlab` users, you should use `utils.get_repo_owner_and_repo(true)`utils.get_repo_owner_and_repo() ..'/issues?state=all&per_page=100&sort=updated'elseargs[#args] ='repos/' ..-- NOTE:-- for `gitlab` users, you should use `utils.get_repo_owner_and_repo(true)`utils.get_repo_owner_and_repo() ..'/issues?state=all&per_page=100&sort=updated'-- use those below to customize the enterprise's domain-- table.insert(args, '--hostname')-- table.insert(args, 'github.com')endreturnargsend, } } }

Note

For github, the per_page has a maximum of 100. See github-discussion-comment.

How to auto reload cache when opening a file from a different repository?

By default, blink-cmp-git will reload the cache when the result of get_cwd is changed to another repository.

The default get_cwd is vim.fn.getcwd. If you want to reload the cache when opening a file from a different repository, you just need to update the get_cwd function. For example:

get_cwd=function() -- return the directory of the current filereturnvim.fn.expand('%:p:h') end

How to add new git platforms?

I've written a post to show you how to add new git platforms. You can see Contributing to blink-cmp-git.

Performance

blink-cmp-git is async. This means that completion won't block other operations. How long it will take to show results depends on the network speed and the response time of the git center. But, don't worry, the items will be cached when you first trigger the completion by inputting @, #, or : (You can DIY the triggers). Furthermore, when the source is created, it will pre-cache all the items. For the documentation of the mention feature, it will be cached when you hover on one item.

Version Introduction

The release versions are something like major.minor.patch. When one of these numbers is increased:

  • patch: bugs are fixed or docs are added. This will not break the compatibility.
  • minor: compatible features are added. This may cause some configurations deprecated, but not break the compatibility.
  • major: incompatible features are added. All the deprecated configurations will be removed. This will break the compatibility.

Acknowledgment

Nice and fast completion plugin: blink.cmp.

Inspired by cmp-git.

About

Git source for blink.cmp

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 7

Languages