comparison plugin/lawrencium.vim @ 49:dffb41c2067c

Lawrencium files changes: - Using double-slashes everywhere for Lawrencium paths. - Added an `action=value` standard, to allow for other things than revisions. - Added support for `diff` action. Added support for showing diffs in `Hglog` window.
author Ludovic Chabant <ludovic@chabant.com>
date Thu, 08 Nov 2012 23:05:44 -0800
parents 85e39bdd7089
children 671f5e18b515
comparison
equal deleted inserted replaced
48:85e39bdd7089 49:dffb41c2067c
111 let l:path = fnamemodify(l:path, ':h') 111 let l:path = fnamemodify(l:path, ':h')
112 endwhile 112 endwhile
113 call s:throw("No Mercurial repository found above: " . a:path) 113 call s:throw("No Mercurial repository found above: " . a:path)
114 endfunction 114 endfunction
115 115
116 " Given a Lawrencium path (e.g: 'lawrencium:///repo/root_dir@foo/bar/file.py//34'), extract 116 " Given a Lawrencium path (e.g: 'lawrencium:///repo/root_dir//foo/bar/file.py//rev=34'), extract
117 " the repository root, relative file path and revision number/changeset ID. 117 " the repository root, relative file path and revision number/changeset ID.
118 function! s:parse_lawrencium_path(lawrencium_path) 118 function! s:parse_lawrencium_path(lawrencium_path)
119 let l:repo_path = s:shellslash(a:lawrencium_path) 119 let l:repo_path = s:shellslash(a:lawrencium_path)
120 if l:repo_path =~? '\v^lawrencium://' 120 if l:repo_path =~? '\v^lawrencium://'
121 let l:repo_path = strpart(l:repo_path, strlen('lawrencium://')) 121 let l:repo_path = strpart(l:repo_path, strlen('lawrencium://'))
122 endif 122 endif
123 123
124 let l:root_dir = '' 124 let l:root_dir = ''
125 let l:at_idx = stridx(l:repo_path, '@') 125 let l:at_idx = stridx(l:repo_path, '//')
126 if l:at_idx >= 0 126 if l:at_idx >= 0
127 let l:root_dir = strpart(l:repo_path, 0, l:at_idx) 127 let l:root_dir = strpart(l:repo_path, 0, l:at_idx)
128 let l:repo_path = strpart(l:repo_path, l:at_idx + 1) 128 let l:repo_path = strpart(l:repo_path, l:at_idx + 2)
129 endif 129 endif
130
131 let l:value = ''
132 let l:action = ''
133 let l:actionidx = stridx(l:repo_path, '//')
134 if l:actionidx >= 0
135 let l:action = strpart(l:repo_path, l:actionidx + 2)
136 let l:repo_path = strpart(l:repo_path, 0, l:actionidx)
137
138 let l:equalidx = stridx(l:action, '=')
139 if l:equalidx >= 0
140 let l:value = strpart(l:action, l:equalidx + 1)
141 let l:action = strpart(l:action, 0, l:equalidx)
142 endif
143 endif
144
145 execute 'cd! ' . l:root_dir
146 let l:absolute_repo_path = fnamemodify(l:repo_path, ':p')
147 let l:relative_repo_path = fnamemodify(l:repo_path, ':.')
148 execute 'cd! -'
130 149
131 let l:rev = matchstr(l:repo_path, '\v//[0-9a-f]+$') 150 let l:result = { 'root': l:root_dir, 'path': l:absolute_repo_path, 'relpath': l:relative_repo_path, 'action': l:action, 'value': l:value }
132 if l:rev !=? ''
133 let l:repo_path = strpart(l:repo_path, 0, strlen(l:repo_path) - strlen(l:rev))
134 let l:rev = strpart(l:rev, 2)
135 endif
136
137 let l:result = { 'root': l:root_dir, 'path': l:repo_path, 'rev': l:rev }
138 return l:result 151 return l:result
139 endfunction 152 endfunction
140 153
141 " }}} 154 " }}}
142 155
203 function! s:HgRepo.RunCommand(command, ...) abort 216 function! s:HgRepo.RunCommand(command, ...) abort
204 let l:all_args = [a:command] + a:000 217 let l:all_args = [a:command] + a:000
205 let l:hg_command = call(self['GetCommand'], l:all_args, self) 218 let l:hg_command = call(self['GetCommand'], l:all_args, self)
206 call s:trace("Running Mercurial command: " . l:hg_command) 219 call s:trace("Running Mercurial command: " . l:hg_command)
207 return system(l:hg_command) 220 return system(l:hg_command)
221 endfunction
222
223 " Runs a Mercurial command in the repo and read it output into the current
224 " buffer.
225 function! s:HgRepo.ReadCommandOutput(command, ...) abort
226 let l:all_args = [a:command] + a:000
227 let l:hg_command = call(self['GetCommand'], l:all_args, self)
228 call s:trace("Running Mercurial command: " . l:hg_command)
229 execute 'read !' . escape(l:hg_command, '%#\')
230 endfunction
231
232 " Build a Lawrencium path for the given file and action.
233 function! s:HgRepo.GetLawrenciumPath(path, action, value) abort
234 execute 'cd! ' . self.root_dir
235 let l:relative_path = fnamemodify(a:path, ':.')
236 execute 'cd! -'
237
238 let l:result = 'lawrencium://' . s:stripslash(self.root_dir) . '//' . l:relative_path
239 if a:action !=? ''
240 let l:result = l:result . '//' . a:action
241 if a:value !=? ''
242 let l:result = l:result . '=' . a:value
243 endif
244 endif
245 return l:result
208 endfunction 246 endfunction
209 247
210 " Repo cache map. 248 " Repo cache map.
211 let s:buffer_repos = {} 249 let s:buffer_repos = {}
212 250
944 " Make commands available. 982 " Make commands available.
945 call s:DefineMainCommands() 983 call s:DefineMainCommands()
946 984
947 " Add some other nice commands and mappings. 985 " Add some other nice commands and mappings.
948 command! -buffer -nargs=? Hglogrevedit :call s:HgLog_FileRevEdit(<f-args>) 986 command! -buffer -nargs=? Hglogrevedit :call s:HgLog_FileRevEdit(<f-args>)
987 command! -buffer -nargs=* Hglogdiff :call s:HgLog_Diff(<f-args>)
988
949 if g:lawrencium_define_mappings 989 if g:lawrencium_define_mappings
950 nnoremap <buffer> <silent> <cr> :Hglogrevedit<cr> 990 nnoremap <buffer> <silent> <cr> :Hglogrevedit<cr>
991 nnoremap <buffer> <silent> <C-D> :Hglogdiff<cr>
951 nnoremap <buffer> <silent> q :bdelete!<cr> 992 nnoremap <buffer> <silent> q :bdelete!<cr>
952 endif 993 endif
953 994
954 " Clean up when the log buffer is deleted. 995 " Clean up when the log buffer is deleted.
955 autocmd BufDelete <buffer> call s:HgLog_Delete(expand('<afile>:p')) 996 autocmd BufDelete <buffer> call s:HgLog_Delete(expand('<afile>:p'))
956 endfunction 997 endfunction
957 998
958 function! s:HgLog_Delete(path) 999 function! s:HgLog_Delete(path)
959 let l:orignr = winnr() 1000 let l:orignr = winnr()
960 let l:origpath = b:mercurial_logged_file 1001 let l:origpath = b:mercurial_logged_file
1002 let l:origroot = s:stripslash(b:mercurial_dir)
961 " Delete any other buffer opened by this log. 1003 " Delete any other buffer opened by this log.
962 " (buffers with Lawrencium paths that match this repo and filename) 1004 " (buffers with Lawrencium paths that match this repo and filename)
963 for nr in range(1, winnr('$')) 1005 for nr in range(1, winnr('$'))
964 let l:br = winbufnr(nr) 1006 let l:br = winbufnr(nr)
965 let l:bpath = bufname(l:br) 1007 let l:bpath = bufname(l:br)
966 let l:bpath_comps = s:parse_lawrencium_path(l:bpath) 1008 let l:bpath_comps = s:parse_lawrencium_path(l:bpath)
967 if l:bpath_comps['root'] != '' 1009 if l:bpath_comps['root'] != ''
968 let l:bpath_root = s:normalizepath(l:bpath_comps['root']) 1010 let l:bpath_root = s:normalizepath(l:bpath_comps['root'])
969 let l:bpath_path = s:normalizepath(l:bpath_comps['path']) 1011 let l:bpath_path = s:normalizepath(l:bpath_comps['path'])
970 if l:bpath_root == b:mercurial_dir && l:bpath_path == b:mercurial_logged_file 1012 if l:bpath_root == l:origroot && l:bpath_path == l:origpath
971 " Go to that window and switch to the previous buffer 1013 " Go to that window and switch to the previous buffer
972 " from the buffer with the file revision. 1014 " from the buffer with the file revision.
973 " Just switching away should delete the buffer since it 1015 " Just switching away should delete the buffer since it
974 " has `bufhidden=delete`. 1016 " has `bufhidden=delete`.
975 echom "Found buffer in window: ".nr
976 execute nr . 'wincmd w' 1017 execute nr . 'wincmd w'
977 let l:altbufname = s:shellslash(bufname('#')) 1018 let l:altbufname = s:shellslash(bufname('#'))
978 if l:altbufname =~# '\v^lawrencium://' 1019 if l:altbufname =~# '\v^lawrencium://'
979 " This is a special Lawrencium buffer... it could be 1020 " This is a special Lawrencium buffer... it could be
980 " a previously shown revision of the file opened with 1021 " a previously shown revision of the file opened with
1004 let l:rev = a:1 1045 let l:rev = a:1
1005 else 1046 else
1006 " Revision should be parsed from the current line in the log. 1047 " Revision should be parsed from the current line in the log.
1007 let l:rev = s:HgLog_GetSelectedRev() 1048 let l:rev = s:HgLog_GetSelectedRev()
1008 endif 1049 endif
1009 let l:path = 'lawrencium://' . b:mercurial_dir . '@' . b:mercurial_logged_file . '//' . l:rev 1050 let l:repo = s:hg_repo()
1010 let l:path = fnameescape(l:path) 1051 let l:path = l:repo.GetLawrenciumPath(b:mercurial_logged_file, 'rev', l:rev)
1011 wincmd p 1052 wincmd p
1012 execute 'edit ' . l:path 1053 execute 'edit ' . fnameescape(l:path)
1013 setlocal bufhidden=delete 1054 endfunction
1014 setlocal buftype=nofile 1055
1015 endfunction 1056 function! s:HgLog_Diff(...) abort
1016 1057 if a:0 >= 2
1017 function! s:HgLog_GetSelectedRev() abort 1058 let l:revs = a:1 . ',' . a:2
1018 let l:line = getline('.') 1059 elseif a:0 == 1
1060 let l:revs = a:1
1061 else
1062 let l:revs = s:HgLog_GetSelectedRev()
1063 endif
1064 let l:repo = s:hg_repo()
1065 let l:path = l:repo.GetLawrenciumPath(b:mercurial_logged_file, 'diff', l:revs)
1066 wincmd p
1067 execute 'edit ' . fnameescape(l:path)
1068 endfunction
1069
1070 function! s:HgLog_GetSelectedRev(...) abort
1071 if a:0 == 1
1072 let l:line = getline(a:1)
1073 else
1074 let l:line = getline('.')
1075 endif
1019 " Behold, Vim's look-ahead regex syntax again! WTF. 1076 " Behold, Vim's look-ahead regex syntax again! WTF.
1020 let l:rev = matchstr(l:line, '\v^(\d+)(\s)@=') 1077 let l:rev = matchstr(l:line, '\v^(\d+)(\s)@=')
1021 if l:rev == '' 1078 if l:rev == ''
1022 call s:throw("Can't parse revision number from line: " . l:line) 1079 call s:throw("Can't parse revision number from line: " . l:line)
1023 endif 1080 endif
1028 1085
1029 " }}} 1086 " }}}
1030 1087
1031 " Lawrencium files {{{ 1088 " Lawrencium files {{{
1032 1089
1033 function! s:ReadFileRevision(path) abort 1090 function! s:ReadLawrenciumFile(path) abort
1091 call s:trace("Reading Lawrencium file '" . a:path)
1034 let l:comps = s:parse_lawrencium_path(a:path) 1092 let l:comps = s:parse_lawrencium_path(a:path)
1035 if l:comps['root'] == '' 1093 if l:comps['root'] == ''
1036 call s:throw("Can't get repository root from: " . a:path) 1094 call s:throw("Can't get repository root from: " . a:path)
1037 endif 1095 endif
1038 let l:repo = s:HgRepo.New(l:comps['root']) 1096
1039 if l:comps['rev'] == '' 1097 let l:repo = s:hg_repo(l:comps['root'])
1040 execute 'read !' . escape(l:repo.GetCommand('cat', l:comps['path']), '%#\') 1098 if l:comps['action'] == 'rev'
1041 else 1099 " Read revision (`hg cat`)
1042 execute 'read !' . escape(l:repo.GetCommand('cat', '-r', l:comps['rev'], l:comps['path']), '%#\') 1100 if l:comps['value'] == ''
1043 endif 1101 call l:repo.ReadCommandOutput('cat', l:comps['path'])
1102 else
1103 call l:repo.ReadCommandOutput('cat', '-r', l:comps['value'], l:comps['path'])
1104 endif
1105 elseif l:comps['action'] == 'diff'
1106 " Diff revisions (`hg diff`)
1107 let l:commaidx = stridx(l:comps['value'], ',')
1108 if l:commaidx > 0
1109 let l:rev1 = strpart(l:comps['value'], 0, l:commaidx)
1110 let l:rev2 = strpart(l:comps['value'], l:commaidx + 1)
1111 if l:rev1 == '-'
1112 call l:repo.ReadCommandOutput('diff', '-r', l:rev2, l:comps['path'])
1113 elseif l:rev2 == '-'
1114 call l:repo.ReadCommandOutput('diff', '-r', l:rev1, l:comps['path'])
1115 else
1116 call l:repo.ReadCommandOutput('diff', '-r', l:rev1, '-r', l:rev2, l:comps['path'])
1117 endif
1118 else
1119 call l:repo.ReadCommandOutput('diff', '-c', l:comps['value'], l:comps['path'])
1120 endif
1121 setlocal filetype=diff
1122 endif
1123
1044 setlocal readonly 1124 setlocal readonly
1045 setlocal nomodifiable
1046 setlocal nomodified 1125 setlocal nomodified
1047 setlocal bufhidden=delete 1126 setlocal bufhidden=delete
1127 setlocal buftype=nofile
1048 return '' 1128 return ''
1049 endfunction 1129 endfunction
1050 1130
1051 augroup lawrencium_files 1131 augroup lawrencium_files
1052 autocmd! 1132 autocmd!
1053 autocmd BufReadCmd lawrencium://**//[0-9a-f]* exe s:ReadFileRevision(expand('<amatch>')) 1133 autocmd BufReadCmd lawrencium://**//**//* exe s:ReadLawrenciumFile(expand('<amatch>'))
1054 augroup END 1134 augroup END
1055 1135
1056 " }}} 1136 " }}}
1057 1137
1058 " Autoload Functions {{{ 1138 " Autoload Functions {{{