git-info.vim
git-info.vim copied to clipboard
Extract git repo information for use in vim status lines.
git-info.vim
A neovim plugin that extracts git repo information to a few global variables for use in your status line (or other things).
Information is extracted via asynchronous background jobs either on buffer load and save.
Information is relative to the current buffer, not vim current working directory.
Currently, git-info is not compatible with VIM due to incompatibilities in the async job API.

Installation
git-info requires neovim v0.3.1+ and is only tested with at least git v2.20+.
Using vim-plug
Plug 'rktjmp/git-info.vim'
Usage
git-info exposes the following functions:
-
git_info#branch_name(): the name of the current branch. -
git_info#last_commit_timestamp(): a number representing the unix timestamp of the last git commit.-1if no commit has been made.- You can convert this to a readable format with time-ago.vim ("10 days ago") or to date with
strftime.
-
git_info#changes(): a map containing the following keys:changed: number of files with uncommitted changes.insertions: number ofdiffinsertions (linewise).deletions: number ofdiffdeletions (linewise).untracked: number of untracked files in the repository directory.as_string: a condensed & opinionated representation of the changes.''if no changes or untracked files.Δ2±3/4∌1: should be read as "the repo delta contains 2 altered files with 3 insertions and 4 deletions. 1 file is untracked (not included in the change set)".Δ5±0/6: 5 files changed, 0 insertions, 6 deletions, no untracked filesΔ0∌2: 0 files changed, 2 untracked files
Lightline Configuration Example
let g:lightline = {
\ 'component_function': {
\ 'git_branch': 'LightlineGitBranchName',
\ 'git_commit_age': 'LightlineGitLastCommit',
\ 'git_status': 'LightlineGitStatus',
\ 'git_dirty': 'LightlineGitDirty',
\ },
\ 'active' : {
\ 'left': [['mode', 'paste'], ['git_branch', 'git_dirty', 'git_commit_age', 'git_status', 'filename']]
\ },
\ }
function! LightlineGitBranchName()
" check if branch name is set, add icon
" else return nothing which hides the subsection
" if you did not want the icon you could just return the branch name
" without checking, which will be blank if not inside a git repo
if len(git_info#branch_name())
return '⭠ ' . git_info#branch_name()
endif
return ''
endfunction
function! LightlineGitDirty()
" dirty flag is left to the user since there are differening opinions
" on whether untracked files count towards 'dirty' status
" git_info#changes().as_string provides the same information
let l:changes = git_info#changes()
if l:changes.changed > 0 || l:changes.untracked > 0
return '*'
endif
return ''
endfunction
function! LightlineGitStatus()
" return the as_string representation, which will be '' if no changes
" are present, which will hide the subsection
return git_info#changes().as_string
endfunction
function! LightlineGitLastCommit()
let l:timestamp = git_info#last_commit_timestamp()
" check if there is no last commit
if l:timestamp == -1
" hide subsection
return ''
endif
" have a commit, convert it to a fuzzy phrase
let l:phrase = time_ago#fuzzy_from_now(l:timestamp)
" minimise the terms
let l:phrase = substitute(l:phrase, 'under a minute', '<1m', '')
let l:phrase = substitute(l:phrase, '\v weeks?', 'w', '')
let l:phrase = substitute(l:phrase, '\v days?', 'd', '')
let l:phrase = substitute(l:phrase, '\v hours?', 'h', '')
let l:phrase = substitute(l:phrase, '\v minutes?', 'm', '')
" remove ', ' if present
let l:phrase = substitute(l:phrase, '\v, ', '', '')
return l:phrase
endfunction
Notes
- Renaming a file with no changes will return 1 file changed and 0 insertions, 0 deletions, 0 untracked.
- Due to the behaviour of git, status details may not be what you expect until at least one commit has been made to a repository.
Bugs
You will sometimes see spurious counts for 'untracked files' when another process is watching for changes in a file you edit.
An example of this might be exuberant ctags if set to create tag files in your working dir.
On save, ctags will create tags.temp and tags.lock, update tags then remove tags.temp and tags.lock. However our git status command is run during this time and spots 2 new untracked files.
The solution to this is adding the additional files to your .gitignore.
TODO
[ ] Remote ahead/behind tracking