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