1" Plugin to update the %changelog section of RPM spec files 2" Filename: spec.vim 3" Maintainer: Gustavo Niemeyer <[email protected]> 4" Last Change: 2012 Mar 07 5 6if exists("b:did_ftplugin") 7 finish 8endif 9let b:did_ftplugin = 1 10 11let s:cpo_save = &cpo 12set cpo&vim 13 14if !exists("no_plugin_maps") && !exists("no_spec_maps") 15 if !hasmapto("<Plug>SpecChangelog") 16 map <buffer> <LocalLeader>c <Plug>SpecChangelog 17 endif 18endif 19 20noremap <buffer> <unique> <script> <Plug>SpecChangelog :call <SID>SpecChangelog("")<CR> 21 22if !exists("*s:SpecChangelog") 23 function s:SpecChangelog(format) 24 if strlen(a:format) == 0 25 if !exists("g:spec_chglog_format") 26 let email = input("Email address: ") 27 let g:spec_chglog_format = "%a %b %d %Y " . l:email 28 echo "\r" 29 endif 30 let format = g:spec_chglog_format 31 else 32 if !exists("g:spec_chglog_format") 33 let g:spec_chglog_format = a:format 34 endif 35 let format = a:format 36 endif 37 let line = 0 38 let name = "" 39 let ver = "" 40 let rel = "" 41 let nameline = -1 42 let verline = -1 43 let relline = -1 44 let chgline = -1 45 while (line <= line("$")) 46 let linestr = getline(line) 47 if (name == "" && linestr =~? '^Name:') 48 let nameline = line 49 let name = substitute(strpart(linestr,5), '^[ ]*\([^ ]\+\)[ ]*$','\1','') 50 elseif (ver == "" && linestr =~? '^Version:') 51 let verline = line 52 let ver = substitute(strpart(linestr,8), '^[ ]*\([^ ]\+\)[ ]*$','\1','') 53 elseif (rel == "" && linestr =~? '^Release:') 54 let relline = line 55 let rel = substitute(strpart(linestr,8), '^[ ]*\([^ ]\+\)[ ]*$','\1','') 56 elseif (linestr =~? '^%changelog') 57 let chgline = line 58 execute line 59 break 60 endif 61 let line = line+1 62 endwhile 63 if (nameline != -1 && verline != -1 && relline != -1) 64 let include_release_info = exists("g:spec_chglog_release_info") 65 let name = s:ParseRpmVars(name, nameline) 66 let ver = s:ParseRpmVars(ver, verline) 67 let rel = s:ParseRpmVars(rel, relline) 68 else 69 let include_release_info = 0 70 endif 71 if (chgline == -1) 72 let option = confirm("Can't find %changelog. Create one? ","&End of file\n&Here\n&Cancel",3) 73 if (option == 1) 74 call append(line("$"),"") 75 call append(line("$"),"%changelog") 76 execute line("$") 77 let chgline = line(".") 78 elseif (option == 2) 79 call append(line("."),"%changelog") 80 normal j 81 chgline = line(".") 82 endif 83 endif 84 if (chgline != -1) 85 let parsed_format = "* ".strftime(format) 86 let release_info = "+ ".name."-".ver."-".rel 87 let wrong_format = 0 88 let wrong_release = 0 89 let insert_line = 0 90 if (getline(chgline+1) != parsed_format) 91 let wrong_format = 1 92 endif 93 if (include_release_info && getline(chgline+2) != release_info) 94 let wrong_release = 1 95 endif 96 if (wrong_format || wrong_release) 97 if (include_release_info && !wrong_release && !exists("g:spec_chglog_never_increase_release")) 98 let option = confirm("Increase release? ","&Yes\n&No",1) 99 if (option == 1) 100 execute relline 101 normal 102 let rel = substitute(strpart(getline(relline),8), '^[ ]*\([^ ]\+\)[ ]*$','\1','') 103 let release_info = "+ ".name."-".ver."-".rel 104 endif 105 endif 106 let n = 0 107 call append(chgline+n, parsed_format) 108 if include_release_info 109 let n = n + 1 110 call append(chgline+n, release_info) 111 endif 112 let n = n + 1 113 call append(chgline+n,"- ") 114 let n = n + 1 115 call append(chgline+n,"") 116 let insert_line = chgline+n 117 else 118 let line = chgline 119 if !exists("g:spec_chglog_prepend") 120 while !(getline(line+2) =~ '^\( *\|\*.*\)$') 121 let line = line+1 122 endwhile 123 endif 124 call append(line+1,"- ") 125 let insert_line = line+2 126 endif 127 execute insert_line 128 startinsert! 129 endif 130 endfunction 131endif 132 133if !exists("*s:ParseRpmVars") 134 function s:ParseRpmVars(str, strline) 135 let end = -1 136 let ret = "" 137 while (1) 138 let start = match(a:str, "\%{", end+1) 139 if (start == -1) 140 let ret = ret . strpart(a:str, end+1) 141 break 142 endif 143 let ret = ret . strpart(a:str, end+1, start-(end+1)) 144 let end = match(a:str, "}", start) 145 if (end == -1) 146 let ret = ret . strpart(a:str, start) 147 break 148 endif 149 let varname = strpart(a:str, start+2, end-(start+2)) 150 execute a:strline 151 let definestr = "^[ \t]*%define[ \t]\\+" . varname . "[ \t]\\+\\(.*\\)$" 152 let linenum = search(definestr, "bW") 153 if (linenum != -1) 154 let ret = ret . substitute(getline(linenum), definestr, "\\1", "") 155 else 156 let ret = ret . strpart(str, start, end+1-start) 157 endif 158 endwhile 159 return ret 160 endfunction 161endif 162 163" The following lines, along with the macros/matchit.vim plugin, 164" make it easy to navigate the different sections of a spec file 165" with the % key (thanks to Max Ischenko). 166 167let b:match_ignorecase = 0 168let b:match_words = 169 \ '^Name:^%description:^%clean:^%setup:^%build:^%install:^%files:' . 170 \ '^%package:^%preun:^%postun:^%changelog' 171 172let &cpo = s:cpo_save 173unlet s:cpo_save 174 175let b:undo_ftplugin = "unlet! b:match_ignorecase b:match_words" 176