Mercurial > vim-lawrencium
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 {{{ |