branch: display dirty state

If the repository is considered dirty, do display the
g:airline_symbols.dirty symbol right after the branch name.
This commit is contained in:
Christian Brabandt 2019-04-24 15:15:29 +02:00
parent a8c96d7c07
commit 9112675ad8
No known key found for this signature in database
GPG Key ID: F3F92DA383FDDE09
5 changed files with 93 additions and 5 deletions

View File

@ -13,6 +13,8 @@ This is the Changelog for the vim-airline project.
buffers directly (issue #1823) buffers directly (issue #1823)
- Allow to use `random` as special theme name, which will switch to a random - Allow to use `random` as special theme name, which will switch to a random
airline theme (at least if a random number can be generated :() airline theme (at least if a random number can be generated :()
- The branch extensions now also displays whether the repository is in a clean state
(will append a ! or ⚡if the repository is considered dirty).
## [0.10] - 2018-12-15 ## [0.10] - 2018-12-15
- New features - New features

View File

@ -6,6 +6,7 @@ scriptencoding utf-8
let s:untracked_jobs = {} let s:untracked_jobs = {}
let s:mq_jobs = {} let s:mq_jobs = {}
let s:po_jobs = {} let s:po_jobs = {}
let s:clean_jobs = {}
" Generic functions handling on exit event of the various async functions " Generic functions handling on exit event of the various async functions
function! s:untracked_output(dict, buf) function! s:untracked_output(dict, buf)
@ -63,6 +64,29 @@ function! airline#async#vcs_untracked(config, file, vcs)
endif endif
endfunction endfunction
function! s:on_exit_clean(...) dict abort
let buf=self.buf
if !empty(buf)
let var=getbufvar(self.file, 'buffer_vcs_config', {})
let var[self.vcs].dirty=1
call setbufvar(self.file, 'buffer_vcs_config', var)
unlet! b:airline_head
endif
if has_key(get(s:clean_jobs, 'self.vcs', {}), self.file)
call remove(s:clean_jobs[self.vcs], self.file)
endif
endfunction
function! airline#async#vcs_clean(cmd, file, vcs)
if g:airline#init#vim_async
" Vim 8 with async support
noa call airline#async#vim_vcs_clean(a:cmd, a:file, a:vcs)
else
" nvim async or vim without job-feature
noa call airline#async#nvim_vcs_clean(a:cmd, a:file, a:vcs)
endif
endfunction
if v:version >= 800 && has("job") if v:version >= 800 && has("job")
" Vim 8.0 with Job feature " Vim 8.0 with Job feature
" TODO: Check if we need the cwd option for the job_start() functions " TODO: Check if we need the cwd option for the job_start() functions
@ -133,6 +157,29 @@ if v:version >= 800 && has("job")
let s:po_jobs[a:file] = id let s:po_jobs[a:file] = id
endfunction endfunction
function! airline#async#vim_vcs_clean(cmd, file, vcs)
if g:airline#init#is_windows && &shell =~ 'cmd'
let cmd = a:cmd
else
let cmd = ['sh', '-c', a:cmd]
endif
let options = {'buf': '', 'vcs': a:vcs, 'file': a:file}
let jobs = get(s:clean_jobs, a:vcs, {})
if has_key(jobs, a:file)
if job_status(get(jobs, a:file)) == 'run'
return
elseif has_key(jobs, a:file)
call remove(jobs, a:file)
endif
endif
let id = job_start(cmd, {
\ 'err_io': 'null',
\ 'out_cb': function('s:on_stdout', options),
\ 'close_cb': function('s:on_exit_clean', options)})
let jobs[a:file] = id
endfunction
function! airline#async#vim_vcs_untracked(config, file) function! airline#async#vim_vcs_untracked(config, file)
if g:airline#init#is_windows && &shell =~ 'cmd' if g:airline#init#is_windows && &shell =~ 'cmd'
let cmd = a:config['cmd'] . shellescape(a:file) let cmd = a:config['cmd'] . shellescape(a:file)
@ -208,6 +255,32 @@ elseif has("nvim")
let s:mq_jobs[a:file] = id let s:mq_jobs[a:file] = id
endfunction endfunction
function! airline#async#nvim_vcs_clean(cmd, file, vcs)
let config = {
\ 'buf': '',
\ 'vcs': a:vcs,
\ 'file': a:file,
\ 'cwd': s:valid_dir(fnamemodify(a:file, ':p:h')),
\ 'on_stdout': function('s:nvim_output_handler'),
\ 'on_stderr': function('s:nvim_output_handler'),
\ 'on_exit': function('s:on_exit_clean')
\ }
if g:airline#init#is_windows && &shell =~ 'cmd'
let cmd = a:cmd
else
let cmd = ['sh', '-c', a:cmd]
endif
if !has_key(s:clean_jobs, a:vcs)
let s:clean_jobs[a:vcs] = {}
endif
if has_key(s:clean_jobs[a:vcs], a:file)
call remove(s:clean_jobs[a:vcs], a:file)
endif
let id = jobstart(cmd, config)
let s:clean_jobs[a:vcs][a:file] = id
endfunction
function! airline#async#nvim_get_msgfmt_stat(cmd, file) function! airline#async#nvim_get_msgfmt_stat(cmd, file)
let config = { let config = {
\ 'buf': '', \ 'buf': '',

View File

@ -17,6 +17,7 @@ let s:vcs_config = {
\ 'git': { \ 'git': {
\ 'exe': 'git', \ 'exe': 'git',
\ 'cmd': 'git status --porcelain -- ', \ 'cmd': 'git status --porcelain -- ',
\ 'dirty': 'git status --porcelain',
\ 'untracked_mark': '??', \ 'untracked_mark': '??',
\ 'exclude': '\.git', \ 'exclude': '\.git',
\ 'update_branch': 's:update_git_branch', \ 'update_branch': 's:update_git_branch',
@ -27,6 +28,7 @@ let s:vcs_config = {
\ 'mercurial': { \ 'mercurial': {
\ 'exe': 'hg', \ 'exe': 'hg',
\ 'cmd': 'hg status -u -- ', \ 'cmd': 'hg status -u -- ',
\ 'dirty': 'hg status -muard',
\ 'untracked_mark': '?', \ 'untracked_mark': '?',
\ 'exclude': '\.hg', \ 'exclude': '\.hg',
\ 'update_branch': 's:update_hg_branch', \ 'update_branch': 's:update_hg_branch',
@ -51,6 +53,7 @@ function! s:init_buffer()
let b:buffer_vcs_config[vcs] = { let b:buffer_vcs_config[vcs] = {
\ 'branch': '', \ 'branch': '',
\ 'untracked': '', \ 'untracked': '',
\ 'dirty': 0,
\ } \ }
endfor endfor
unlet! b:airline_head unlet! b:airline_head
@ -200,6 +203,8 @@ function! s:update_untracked()
" result of the previous call, i.e. the head string is not updated. It " result of the previous call, i.e. the head string is not updated. It
" doesn't happen often in practice, so we let it be. " doesn't happen often in practice, so we let it be.
call airline#async#vcs_untracked(config, file, vcs) call airline#async#vcs_untracked(config, file, vcs)
" Check clean state of repo
call airline#async#vcs_clean(config.dirty, file, vcs)
endfor endfor
endfunction endfunction
@ -233,7 +238,11 @@ function! airline#extensions#branch#head()
let b:airline_head .= s:vcs_config[vcs].exe .':' let b:airline_head .= s:vcs_config[vcs].exe .':'
endif endif
let b:airline_head .= s:format_name({s:vcs_config[vcs].display_branch}()) let b:airline_head .= s:format_name({s:vcs_config[vcs].display_branch}())
let b:airline_head .= b:buffer_vcs_config[vcs].untracked let additional = b:buffer_vcs_config[vcs].untracked
if empty(additional) && b:buffer_vcs_config[vcs].dirty
let additional = g:airline_symbols['dirty']
endif
let b:airline_head .= additional
endfor endfor
if empty(heads) if empty(heads)
@ -269,10 +278,10 @@ function! airline#extensions#branch#get_head()
let winwidth = get(airline#parts#get('branch'), 'minwidth', 120) let winwidth = get(airline#parts#get('branch'), 'minwidth', 120)
let minwidth = empty(get(b:, 'airline_hunks', '')) ? 14 : 7 let minwidth = empty(get(b:, 'airline_hunks', '')) ? 14 : 7
let head = airline#util#shorten(head, winwidth, minwidth) let head = airline#util#shorten(head, winwidth, minwidth)
let empty_message = get(g:, 'airline#extensions#branch#empty_message', '')
let symbol = get(g:, 'airline#extensions#branch#symbol', g:airline_symbols.branch) let symbol = get(g:, 'airline#extensions#branch#symbol', g:airline_symbols.branch)
let dirty = get(b:, 'airline_branch_dirty', '')
return empty(head) return empty(head)
\ ? empty_message \ ? get(g:, 'airline#extensions#branch#empty_message', '')
\ : printf('%s%s', empty(symbol) ? '' : symbol.(g:airline_symbols.space), head) \ : printf('%s%s', empty(symbol) ? '' : symbol.(g:airline_symbols.space), head)
endfunction endfunction

View File

@ -86,7 +86,7 @@ function! airline#init#bootstrap()
call s:check_defined('g:airline_left_alt_sep', "\ue0b1") "  call s:check_defined('g:airline_left_alt_sep', "\ue0b1") " 
call s:check_defined('g:airline_right_sep', "\ue0b2") "  call s:check_defined('g:airline_right_sep', "\ue0b2") " 
call s:check_defined('g:airline_right_alt_sep', "\ue0b3") "  call s:check_defined('g:airline_right_alt_sep', "\ue0b3") " 
" ro=, ws=☲, lnr=☰, mlnr=, br=, nx=Ɇ, crypt=🔒 " ro=, ws=☲, lnr=☰, mlnr=, br=, nx=Ɇ, crypt=🔒, dirty=⚡
call extend(g:airline_symbols, { call extend(g:airline_symbols, {
\ 'readonly': "\ue0a2", \ 'readonly': "\ue0a2",
\ 'whitespace': "\u2632", \ 'whitespace': "\u2632",
@ -94,6 +94,7 @@ function! airline#init#bootstrap()
\ 'maxlinenr': " \ue0a1", \ 'maxlinenr': " \ue0a1",
\ 'branch': "\ue0a0", \ 'branch': "\ue0a0",
\ 'notexists': "\u0246", \ 'notexists': "\u0246",
\ 'dirty': "\u26a1",
\ 'crypt': nr2char(0x1F512), \ 'crypt': nr2char(0x1F512),
\ }, 'keep') \ }, 'keep')
elseif &encoding==?'utf-8' && !get(g:, "airline_symbols_ascii", 0) elseif &encoding==?'utf-8' && !get(g:, "airline_symbols_ascii", 0)
@ -111,6 +112,7 @@ function! airline#init#bootstrap()
\ 'branch': "\u16A0", \ 'branch': "\u16A0",
\ 'notexists': "\u0246", \ 'notexists': "\u0246",
\ 'crypt': nr2char(0x1F512), \ 'crypt': nr2char(0x1F512),
\ 'dirty': '!',
\ }, 'keep') \ }, 'keep')
else else
" Symbols for ASCII terminals " Symbols for ASCII terminals

View File

@ -319,6 +319,7 @@ its contents. >
let g:airline_symbols.readonly = '' let g:airline_symbols.readonly = ''
let g:airline_symbols.linenr = '☰' let g:airline_symbols.linenr = '☰'
let g:airline_symbols.maxlinenr = '' let g:airline_symbols.maxlinenr = ''
let g:airline_symbols.dirty=⚡
" old vim-powerline symbols " old vim-powerline symbols
let g:airline_left_sep = '⮀' let g:airline_left_sep = '⮀'
@ -434,7 +435,8 @@ lawrencium <https://bitbucket.org/ludovicchabant/vim-lawrencium>
vcscommand <http://www.vim.org/scripts/script.php?script_id=90> vcscommand <http://www.vim.org/scripts/script.php?script_id=90>
If a file is edited, that is not yet in the repository, the If a file is edited, that is not yet in the repository, the
notexists symbol will be displayed after the branch name. notexists symbol will be displayed after the branch name. If the repository is
not clean, the dirty symbol will be displayed after the branch name.
* enable/disable fugitive/lawrencium integration > * enable/disable fugitive/lawrencium integration >
let g:airline#extensions#branch#enabled = 1 let g:airline#extensions#branch#enabled = 1