From dfe985a1a6643d4aa9d64568be457cbeee101eb5 Mon Sep 17 00:00:00 2001 From: Andy Stewart Date: Fri, 14 Nov 2014 12:55:40 +0100 Subject: [PATCH] Use buffer numbers instead of buffer names. Also don't pass buffer number to functions when they can look it up themselves. Using buffer numbers also eliminates any ambiguity which might arise from symbolic links, where you have potentially two names for a file. Thanks to @Z1MM32M4N for work on this (see #209). --- autoload/gitgutter.vim | 26 ++++++------ autoload/gitgutter/sign.vim | 77 ++++++++++++++++++---------------- autoload/gitgutter/utility.vim | 29 ++++++------- plugin/gitgutter.vim | 8 ++-- 4 files changed, 74 insertions(+), 66 deletions(-) diff --git a/autoload/gitgutter.vim b/autoload/gitgutter.vim index b9f48f6..be574e5 100644 --- a/autoload/gitgutter.vim +++ b/autoload/gitgutter.vim @@ -4,36 +4,36 @@ function! gitgutter#all() for buffer_id in tabpagebuflist() let file = expand('#' . buffer_id . ':p') if !empty(file) - call gitgutter#process_buffer(file, 0) + call gitgutter#process_buffer(buffer_id, 0) endif endfor endfunction -" file: (string) the file to process. +" bufnr: (integer) the buffer to process. " realtime: (boolean) when truthy, do a realtime diff; otherwise do a disk-based diff. -function! gitgutter#process_buffer(file, realtime) - call gitgutter#utility#set_file(a:file) +function! gitgutter#process_buffer(bufnr, realtime) + call gitgutter#utility#set_buffer(a:bufnr) if gitgutter#utility#is_active() if g:gitgutter_sign_column_always call gitgutter#sign#add_dummy_sign() endif try - if !a:realtime || gitgutter#utility#has_fresh_changes(a:file) - let diff = gitgutter#diff#run_diff(a:realtime || gitgutter#utility#has_unsaved_changes(a:file), 1, 0) + if !a:realtime || gitgutter#utility#has_fresh_changes() + let diff = gitgutter#diff#run_diff(a:realtime || gitgutter#utility#has_unsaved_changes(), 1, 0) call gitgutter#hunk#set_hunks(gitgutter#diff#parse_diff(diff)) let modified_lines = gitgutter#diff#process_hunks(gitgutter#hunk#hunks()) if len(modified_lines) > g:gitgutter_max_signs call gitgutter#utility#warn('exceeded maximum number of signs (configured by g:gitgutter_max_signs).') - call gitgutter#sign#clear_signs(a:file) + call gitgutter#sign#clear_signs() return endif if g:gitgutter_signs || g:gitgutter_highlight_lines - call gitgutter#sign#update_signs(a:file, modified_lines) + call gitgutter#sign#update_signs(modified_lines) endif - call gitgutter#utility#save_last_seen_change(a:file) + call gitgutter#utility#save_last_seen_change() endif catch /diff failed/ call gitgutter#hunk#reset() @@ -53,8 +53,8 @@ function! gitgutter#disable() for buffer_id in buflist let file = expand('#' . buffer_id . ':p') if !empty(file) - call gitgutter#utility#set_file(file) - call gitgutter#sign#clear_signs(gitgutter#utility#file()) + call gitgutter#utility#set_buffer(buffer_id) + call gitgutter#sign#clear_signs() call gitgutter#sign#remove_dummy_sign(1) call gitgutter#hunk#reset() endif @@ -85,7 +85,7 @@ function! gitgutter#line_highlights_disable() call gitgutter#highlight#define_sign_line_highlights() if !g:gitgutter_signs - call gitgutter#sign#clear_signs(gitgutter#utility#file()) + call gitgutter#sign#clear_signs() call gitgutter#sign#remove_dummy_sign(0) endif @@ -133,7 +133,7 @@ function! gitgutter#signs_disable() call gitgutter#highlight#define_sign_text_highlights() if !g:gitgutter_highlight_lines - call gitgutter#sign#clear_signs(gitgutter#utility#file()) + call gitgutter#sign#clear_signs() call gitgutter#sign#remove_dummy_sign(0) endif endfunction diff --git a/autoload/gitgutter/sign.vim b/autoload/gitgutter/sign.vim index 60d3978..d170a42 100644 --- a/autoload/gitgutter/sign.vim +++ b/autoload/gitgutter/sign.vim @@ -10,33 +10,34 @@ let s:dummy_sign_id = s:first_sign_id - 1 let s:supports_star = v:version > 703 || (v:version == 703 && has("patch596")) -" Removes gitgutter's signs (excluding dummy sign) from the given file. -function! gitgutter#sign#clear_signs(file_name) - call gitgutter#sign#find_current_signs(a:file_name) +" Removes gitgutter's signs (excluding dummy sign) from the buffer being processed. +function! gitgutter#sign#clear_signs() + let bufnr = gitgutter#utility#bufnr() + call gitgutter#sign#find_current_signs() - let sign_ids = map(values(getbufvar(a:file_name, 'gitgutter_gitgutter_signs')), 'v:val.id') - call gitgutter#sign#remove_signs(sign_ids, a:file_name, 1) - call setbufvar(a:file_name, 'gitgutter_gitgutter_signs', {}) + let sign_ids = map(values(getbufvar(bufnr, 'gitgutter_gitgutter_signs')), 'v:val.id') + call gitgutter#sign#remove_signs(sign_ids, 1) + call setbufvar(bufnr, 'gitgutter_gitgutter_signs', {}) endfunction -" Updates gitgutter's signs in the given file. +" Updates gitgutter's signs in the buffer being processed. " " modified_lines: list of [, ] " where name = 'added|removed|modified|modified_removed' -function! gitgutter#sign#update_signs(file_name, modified_lines) - call gitgutter#sign#find_current_signs(a:file_name) +function! gitgutter#sign#update_signs(modified_lines) + call gitgutter#sign#find_current_signs() let new_gitgutter_signs_line_numbers = map(copy(a:modified_lines), 'v:val[0]') - let obsolete_signs = gitgutter#sign#obsolete_gitgutter_signs_to_remove(a:file_name, new_gitgutter_signs_line_numbers) + let obsolete_signs = gitgutter#sign#obsolete_gitgutter_signs_to_remove(new_gitgutter_signs_line_numbers) let flicker_possible = s:remove_all_old_signs && !empty(a:modified_lines) if flicker_possible call gitgutter#sign#add_dummy_sign() endif - call gitgutter#sign#remove_signs(obsolete_signs, a:file_name, s:remove_all_old_signs) - call gitgutter#sign#upsert_new_gitgutter_signs(a:file_name, a:modified_lines) + call gitgutter#sign#remove_signs(obsolete_signs, s:remove_all_old_signs) + call gitgutter#sign#upsert_new_gitgutter_signs(a:modified_lines) if flicker_possible call gitgutter#sign#remove_dummy_sign(0) @@ -45,16 +46,18 @@ endfunction function! gitgutter#sign#add_dummy_sign() - if !getbufvar(gitgutter#utility#file(), 'gitgutter_dummy_sign') - execute "sign place" s:dummy_sign_id "line=" . 9999 "name=GitGutterDummy file=" . gitgutter#utility#file() - call setbufvar(gitgutter#utility#file(), 'gitgutter_dummy_sign', 1) + let bufnr = gitgutter#utility#bufnr() + if !getbufvar(bufnr, 'gitgutter_dummy_sign') + execute "sign place" s:dummy_sign_id "line=" . 9999 "name=GitGutterDummy buffer=" . bufnr + call setbufvar(bufnr, 'gitgutter_dummy_sign', 1) endif endfunction function! gitgutter#sign#remove_dummy_sign(force) - if getbufvar(gitgutter#utility#file(), 'gitgutter_dummy_sign') && (a:force || !g:gitgutter_sign_column_always) - execute "sign unplace" s:dummy_sign_id "file=" . gitgutter#utility#file() - call setbufvar(gitgutter#utility#file(), 'gitgutter_dummy_sign', 0) + let bufnr = gitgutter#utility#bufnr() + if getbufvar(bufnr, 'gitgutter_dummy_sign') && (a:force || !g:gitgutter_sign_column_always) + execute "sign unplace" s:dummy_sign_id "buffer=" . bufnr + call setbufvar(bufnr, 'gitgutter_dummy_sign', 0) endif endfunction @@ -64,13 +67,14 @@ endfunction " -function! gitgutter#sign#find_current_signs(file_name) +function! gitgutter#sign#find_current_signs() + let bufnr = gitgutter#utility#bufnr() let gitgutter_signs = {} " : {'id': , 'name': } let other_signs = [] " [ signs - silent execute "sign place file=" . a:file_name + silent execute "sign place buffer=" . bufnr redir END for sign_line in filter(split(signs, '\n'), 'v:val =~# "="') @@ -97,18 +101,19 @@ function! gitgutter#sign#find_current_signs(file_name) end endfor - call setbufvar(a:file_name, 'gitgutter_dummy_sign', dummy_sign_placed) - call setbufvar(a:file_name, 'gitgutter_gitgutter_signs', gitgutter_signs) - call setbufvar(a:file_name, 'gitgutter_other_signs', other_signs) + call setbufvar(bufnr, 'gitgutter_dummy_sign', dummy_sign_placed) + call setbufvar(bufnr, 'gitgutter_gitgutter_signs', gitgutter_signs) + call setbufvar(bufnr, 'gitgutter_other_signs', other_signs) endfunction " Returns a list of [, ...] " Sets `s:remove_all_old_signs` as a side-effect. -function! gitgutter#sign#obsolete_gitgutter_signs_to_remove(file_name, new_gitgutter_signs_line_numbers) +function! gitgutter#sign#obsolete_gitgutter_signs_to_remove(new_gitgutter_signs_line_numbers) + let bufnr = gitgutter#utility#bufnr() let signs_to_remove = [] " list of [, ...] let remove_all_signs = 1 - let old_gitgutter_signs = getbufvar(a:file_name, 'gitgutter_gitgutter_signs') + let old_gitgutter_signs = getbufvar(bufnr, 'gitgutter_gitgutter_signs') for line_number in keys(old_gitgutter_signs) if index(a:new_gitgutter_signs_line_numbers, str2nr(line_number)) == -1 call add(signs_to_remove, old_gitgutter_signs[line_number].id) @@ -121,12 +126,13 @@ function! gitgutter#sign#obsolete_gitgutter_signs_to_remove(file_name, new_gitgu endfunction -function! gitgutter#sign#remove_signs(sign_ids, file_name, all_signs) - if a:all_signs && s:supports_star && empty(getbufvar(a:file_name, 'gitgutter_other_signs')) - let dummy_sign_present = getbufvar(a:file_name, 'gitgutter_dummy_sign') - execute "sign unplace * file=" . a:file_name +function! gitgutter#sign#remove_signs(sign_ids, all_signs) + let bufnr = gitgutter#utility#bufnr() + if a:all_signs && s:supports_star && empty(getbufvar(bufnr, 'gitgutter_other_signs')) + let dummy_sign_present = getbufvar(bufnr, 'gitgutter_dummy_sign') + execute "sign unplace * buffer=" . bufnr if dummy_sign_present - execute "sign place" s:dummy_sign_id "line=" . 9999 "name=GitGutterDummy file=" . a:file_name + execute "sign place" s:dummy_sign_id "line=" . 9999 "name=GitGutterDummy buffer=" . bufnr endif else for id in a:sign_ids @@ -136,9 +142,10 @@ function! gitgutter#sign#remove_signs(sign_ids, file_name, all_signs) endfunction -function! gitgutter#sign#upsert_new_gitgutter_signs(file_name, modified_lines) - let other_signs = getbufvar(a:file_name, 'gitgutter_other_signs') - let old_gitgutter_signs = getbufvar(a:file_name, 'gitgutter_gitgutter_signs') +function! gitgutter#sign#upsert_new_gitgutter_signs(modified_lines) + let bufnr = gitgutter#utility#bufnr() + let other_signs = getbufvar(bufnr, 'gitgutter_other_signs') + let old_gitgutter_signs = getbufvar(bufnr, 'gitgutter_gitgutter_signs') for line in a:modified_lines let line_number = line[0] " @@ -146,11 +153,11 @@ function! gitgutter#sign#upsert_new_gitgutter_signs(file_name, modified_lines) let name = gitgutter#utility#highlight_name_for_change(line[1]) if !has_key(old_gitgutter_signs, line_number) " insert let id = gitgutter#sign#next_sign_id() - execute "sign place" id "line=" . line_number "name=" . name "file=" . a:file_name + execute "sign place" id "line=" . line_number "name=" . name "buffer=" . bufnr else " update if sign has changed let old_sign = old_gitgutter_signs[line_number] if old_sign.name !=# name - execute "sign place" old_sign.id "name=" . name "file=" . a:file_name + execute "sign place" old_sign.id "name=" . name "buffer=" . bufnr end endif endif diff --git a/autoload/gitgutter/utility.vim b/autoload/gitgutter/utility.vim index 3a057eb..9f473f3 100644 --- a/autoload/gitgutter/utility.vim +++ b/autoload/gitgutter/utility.vim @@ -30,12 +30,13 @@ function! gitgutter#utility#shellescape(arg) endif endfunction -function! gitgutter#utility#current_file() - return expand('%:p') +function! gitgutter#utility#set_buffer(bufnr) + let s:bufnr = a:bufnr + let s:file = bufname(a:bufnr) endfunction -function! gitgutter#utility#set_file(file) - let s:file = a:file +function! gitgutter#utility#bufnr() + return s:bufnr endfunction function! gitgutter#utility#file() @@ -51,19 +52,19 @@ function! gitgutter#utility#directory_of_file() endfunction function! gitgutter#utility#exists_file() - return filereadable(gitgutter#utility#file()) + return filereadable(s:file) endfunction -function! gitgutter#utility#has_unsaved_changes(file) - return getbufvar(a:file, "&mod") +function! gitgutter#utility#has_unsaved_changes() + return getbufvar(s:bufnr, "&mod") endfunction -function! gitgutter#utility#has_fresh_changes(file) - return getbufvar(a:file, 'changedtick') != getbufvar(a:file, 'gitgutter_last_tick') +function! gitgutter#utility#has_fresh_changes() + return getbufvar(s:bufnr, 'changedtick') != getbufvar(s:bufnr, 'gitgutter_last_tick') endfunction -function! gitgutter#utility#save_last_seen_change(file) - call setbufvar(a:file, 'gitgutter_last_tick', getbufvar(a:file, 'changedtick')) +function! gitgutter#utility#save_last_seen_change() + call setbufvar(s:bufnr, 'gitgutter_last_tick', getbufvar(s:bufnr, 'changedtick')) endfunction function! gitgutter#utility#buffer_contents() @@ -74,7 +75,7 @@ function! gitgutter#utility#buffer_contents() else let eol = "\n" endif - return join(getbufline(s:file, 1, '$'), eol) . eol + return join(getbufline(s:bufnr, 1, '$'), eol) . eol endfunction function! gitgutter#utility#shell_error() @@ -112,12 +113,12 @@ function! gitgutter#utility#system(cmd, ...) endfunction function! gitgutter#utility#file_relative_to_repo_root() - let file_path_relative_to_repo_root = getbufvar(s:file, 'gitgutter_repo_relative_path') + let file_path_relative_to_repo_root = getbufvar(s:bufnr, 'gitgutter_repo_relative_path') if empty(file_path_relative_to_repo_root) let dir_path_relative_to_repo_root = gitgutter#utility#system(gitgutter#utility#command_in_directory_of_file('git rev-parse --show-prefix')) let dir_path_relative_to_repo_root = gitgutter#utility#strip_trailing_new_line(dir_path_relative_to_repo_root) let file_path_relative_to_repo_root = dir_path_relative_to_repo_root . gitgutter#utility#filename() - call setbufvar(s:file, 'gitgutter_repo_relative_path', file_path_relative_to_repo_root) + call setbufvar(s:bufnr, 'gitgutter_repo_relative_path', file_path_relative_to_repo_root) endif return file_path_relative_to_repo_root endfunction diff --git a/plugin/gitgutter.vim b/plugin/gitgutter.vim index 526487d..47ecb01 100644 --- a/plugin/gitgutter.vim +++ b/plugin/gitgutter.vim @@ -53,7 +53,7 @@ call gitgutter#highlight#define_signs() " Primary functions {{{ command GitGutterAll call gitgutter#all() -command GitGutter call gitgutter#process_buffer(gitgutter#utility#current_file(), 0) +command GitGutter call gitgutter#process_buffer(bufnr(''), 0) command GitGutterDisable call gitgutter#disable() command GitGutterEnable call gitgutter#enable() @@ -157,7 +157,7 @@ augroup gitgutter autocmd! if g:gitgutter_realtime - autocmd CursorHold,CursorHoldI * call gitgutter#process_buffer(gitgutter#utility#current_file(), 1) + autocmd CursorHold,CursorHoldI * call gitgutter#process_buffer(bufnr(''), 1) endif if g:gitgutter_eager @@ -165,7 +165,7 @@ augroup gitgutter \ if gettabvar(tabpagenr(), 'gitgutter_didtabenter') | \ call settabvar(tabpagenr(), 'gitgutter_didtabenter', 0) | \ else | - \ call gitgutter#process_buffer(gitgutter#utility#current_file(), 0) | + \ call gitgutter#process_buffer(bufnr(''), 0) | \ endif autocmd TabEnter * \ call settabvar(tabpagenr(), 'gitgutter_didtabenter', 1) | @@ -174,7 +174,7 @@ augroup gitgutter autocmd FocusGained * call gitgutter#all() endif else - autocmd BufRead,BufWritePost,FileChangedShellPost * call gitgutter#process_buffer(gitgutter#utility#current_file(), 0) + autocmd BufRead,BufWritePost,FileChangedShellPost * call gitgutter#process_buffer(bufnr(''), 0) endif autocmd ColorScheme * call gitgutter#highlight#define_sign_column_highlight() | call gitgutter#highlight#define_highlights()