1071d4279SBram Moolenaar" Plugin to update the %changelog section of RPM spec files 2071d4279SBram Moolenaar" Filename: spec.vim 30858917eSBram Moolenaar" Maintainer: Igor Gnatenko [email protected] 40858917eSBram Moolenaar" Former Maintainer: Gustavo Niemeyer <[email protected]> (until March 2014) 5f2571c61SBram Moolenaar" Last Change: Mon Jun 01 21:15 MSK 2015 Igor Gnatenko 6071d4279SBram Moolenaar 7071d4279SBram Moolenaarif exists("b:did_ftplugin") 8071d4279SBram Moolenaar finish 9071d4279SBram Moolenaarendif 10071d4279SBram Moolenaarlet b:did_ftplugin = 1 11071d4279SBram Moolenaar 12b6b046b2SBram Moolenaarlet s:cpo_save = &cpo 13b6b046b2SBram Moolenaarset cpo&vim 14b6b046b2SBram Moolenaar 15071d4279SBram Moolenaarif !exists("no_plugin_maps") && !exists("no_spec_maps") 16071d4279SBram Moolenaar if !hasmapto("<Plug>SpecChangelog") 17071d4279SBram Moolenaar map <buffer> <LocalLeader>c <Plug>SpecChangelog 18071d4279SBram Moolenaar endif 19071d4279SBram Moolenaarendif 20071d4279SBram Moolenaar 21*113cb513SBram Moolenaarif !hasmapto("call <SID>SpecChangelog(\"\")<CR>") 22*113cb513SBram Moolenaar noremap <buffer> <unique> <script> <Plug>SpecChangelog :call <SID>SpecChangelog("")<CR> 232b8388bdSBram Moolenaarendif 24071d4279SBram Moolenaar 25f2571c61SBram Moolenaarif !exists("*s:GetRelVer") 26f2571c61SBram Moolenaar function! s:GetRelVer() 27f2571c61SBram Moolenaar if has('python') 28f2571c61SBram Moolenaarpython << PYEND 29f2571c61SBram Moolenaarimport sys, datetime, shutil, tempfile 30f2571c61SBram Moolenaarimport vim 31f2571c61SBram Moolenaar 32f2571c61SBram Moolenaartry: 33f2571c61SBram Moolenaar import rpm 34f2571c61SBram Moolenaarexcept ImportError: 35f2571c61SBram Moolenaar pass 36f2571c61SBram Moolenaarelse: 37f2571c61SBram Moolenaar specfile = vim.current.buffer.name 38f2571c61SBram Moolenaar if specfile: 3982af8710SBram Moolenaar rpm.delMacro("dist") 40f2571c61SBram Moolenaar spec = rpm.spec(specfile) 4182af8710SBram Moolenaar headers = spec.sourceHeader 4282af8710SBram Moolenaar version = headers["Version"] 4382af8710SBram Moolenaar release = headers["Release"] 44f2571c61SBram Moolenaar vim.command("let ver = " + version) 45f2571c61SBram Moolenaar vim.command("let rel = " + release) 46f2571c61SBram MoolenaarPYEND 47f2571c61SBram Moolenaar endif 48f2571c61SBram Moolenaar endfunction 49f2571c61SBram Moolenaarendif 50f2571c61SBram Moolenaar 51071d4279SBram Moolenaarif !exists("*s:SpecChangelog") 52071d4279SBram Moolenaar function s:SpecChangelog(format) 53071d4279SBram Moolenaar if strlen(a:format) == 0 54071d4279SBram Moolenaar if !exists("g:spec_chglog_format") 55f2571c61SBram Moolenaar let email = input("Name <email address>: ") 56071d4279SBram Moolenaar let g:spec_chglog_format = "%a %b %d %Y " . l:email 57071d4279SBram Moolenaar echo "\r" 58071d4279SBram Moolenaar endif 59071d4279SBram Moolenaar let format = g:spec_chglog_format 60071d4279SBram Moolenaar else 61071d4279SBram Moolenaar if !exists("g:spec_chglog_format") 62071d4279SBram Moolenaar let g:spec_chglog_format = a:format 63071d4279SBram Moolenaar endif 64071d4279SBram Moolenaar let format = a:format 65071d4279SBram Moolenaar endif 66071d4279SBram Moolenaar let line = 0 67071d4279SBram Moolenaar let name = "" 68071d4279SBram Moolenaar let ver = "" 69071d4279SBram Moolenaar let rel = "" 70071d4279SBram Moolenaar let nameline = -1 71071d4279SBram Moolenaar let verline = -1 72071d4279SBram Moolenaar let relline = -1 73071d4279SBram Moolenaar let chgline = -1 74071d4279SBram Moolenaar while (line <= line("$")) 75071d4279SBram Moolenaar let linestr = getline(line) 764072ba57SBram Moolenaar if name == "" && linestr =~? '^Name:' 77071d4279SBram Moolenaar let nameline = line 78071d4279SBram Moolenaar let name = substitute(strpart(linestr,5), '^[ ]*\([^ ]\+\)[ ]*$','\1','') 794072ba57SBram Moolenaar elseif ver == "" && linestr =~? '^Version:' 80071d4279SBram Moolenaar let verline = line 81071d4279SBram Moolenaar let ver = substitute(strpart(linestr,8), '^[ ]*\([^ ]\+\)[ ]*$','\1','') 824072ba57SBram Moolenaar elseif rel == "" && linestr =~? '^Release:' 83071d4279SBram Moolenaar let relline = line 84071d4279SBram Moolenaar let rel = substitute(strpart(linestr,8), '^[ ]*\([^ ]\+\)[ ]*$','\1','') 854072ba57SBram Moolenaar elseif linestr =~? '^%changelog' 86071d4279SBram Moolenaar let chgline = line 87071d4279SBram Moolenaar execute line 88071d4279SBram Moolenaar break 89071d4279SBram Moolenaar endif 90071d4279SBram Moolenaar let line = line+1 91071d4279SBram Moolenaar endwhile 924072ba57SBram Moolenaar if nameline != -1 && verline != -1 && relline != -1 93071d4279SBram Moolenaar let include_release_info = exists("g:spec_chglog_release_info") 94071d4279SBram Moolenaar let name = s:ParseRpmVars(name, nameline) 95071d4279SBram Moolenaar let ver = s:ParseRpmVars(ver, verline) 96071d4279SBram Moolenaar let rel = s:ParseRpmVars(rel, relline) 97071d4279SBram Moolenaar else 98071d4279SBram Moolenaar let include_release_info = 0 99071d4279SBram Moolenaar endif 100f2571c61SBram Moolenaar 101f2571c61SBram Moolenaar call s:GetRelVer() 102f2571c61SBram Moolenaar 1034072ba57SBram Moolenaar if chgline == -1 104071d4279SBram Moolenaar let option = confirm("Can't find %changelog. Create one? ","&End of file\n&Here\n&Cancel",3) 1054072ba57SBram Moolenaar if option == 1 106071d4279SBram Moolenaar call append(line("$"),"") 107071d4279SBram Moolenaar call append(line("$"),"%changelog") 108071d4279SBram Moolenaar execute line("$") 109071d4279SBram Moolenaar let chgline = line(".") 1104072ba57SBram Moolenaar elseif option == 2 111071d4279SBram Moolenaar call append(line("."),"%changelog") 112071d4279SBram Moolenaar normal j 1134072ba57SBram Moolenaar let chgline = line(".") 114071d4279SBram Moolenaar endif 115071d4279SBram Moolenaar endif 1164072ba57SBram Moolenaar if chgline != -1 11782af8710SBram Moolenaar let tmptime = v:lc_time 11882af8710SBram Moolenaar language time C 119f2571c61SBram Moolenaar let parsed_format = "* ".strftime(format)." - ".ver."-".rel 12082af8710SBram Moolenaar execute "language time" tmptime 121071d4279SBram Moolenaar let release_info = "+ ".name."-".ver."-".rel 122071d4279SBram Moolenaar let wrong_format = 0 123071d4279SBram Moolenaar let wrong_release = 0 124071d4279SBram Moolenaar let insert_line = 0 1254072ba57SBram Moolenaar if getline(chgline+1) != parsed_format 126071d4279SBram Moolenaar let wrong_format = 1 127071d4279SBram Moolenaar endif 1284072ba57SBram Moolenaar if include_release_info && getline(chgline+2) != release_info 129071d4279SBram Moolenaar let wrong_release = 1 130071d4279SBram Moolenaar endif 1314072ba57SBram Moolenaar if wrong_format || wrong_release 1324072ba57SBram Moolenaar if include_release_info && !wrong_release && !exists("g:spec_chglog_never_increase_release") 133071d4279SBram Moolenaar let option = confirm("Increase release? ","&Yes\n&No",1) 1344072ba57SBram Moolenaar if option == 1 135071d4279SBram Moolenaar execute relline 136071d4279SBram Moolenaar normal 137071d4279SBram Moolenaar let rel = substitute(strpart(getline(relline),8), '^[ ]*\([^ ]\+\)[ ]*$','\1','') 138071d4279SBram Moolenaar let release_info = "+ ".name."-".ver."-".rel 139071d4279SBram Moolenaar endif 140071d4279SBram Moolenaar endif 141071d4279SBram Moolenaar let n = 0 142071d4279SBram Moolenaar call append(chgline+n, parsed_format) 143071d4279SBram Moolenaar if include_release_info 144071d4279SBram Moolenaar let n = n + 1 145071d4279SBram Moolenaar call append(chgline+n, release_info) 146071d4279SBram Moolenaar endif 147071d4279SBram Moolenaar let n = n + 1 148071d4279SBram Moolenaar call append(chgline+n,"- ") 149071d4279SBram Moolenaar let n = n + 1 150071d4279SBram Moolenaar call append(chgline+n,"") 151071d4279SBram Moolenaar let insert_line = chgline+n 152071d4279SBram Moolenaar else 153071d4279SBram Moolenaar let line = chgline 154071d4279SBram Moolenaar if !exists("g:spec_chglog_prepend") 155071d4279SBram Moolenaar while !(getline(line+2) =~ '^\( *\|\*.*\)$') 156071d4279SBram Moolenaar let line = line+1 157071d4279SBram Moolenaar endwhile 158071d4279SBram Moolenaar endif 159071d4279SBram Moolenaar call append(line+1,"- ") 160071d4279SBram Moolenaar let insert_line = line+2 161071d4279SBram Moolenaar endif 162071d4279SBram Moolenaar execute insert_line 163071d4279SBram Moolenaar startinsert! 164071d4279SBram Moolenaar endif 165071d4279SBram Moolenaar endfunction 166071d4279SBram Moolenaarendif 167071d4279SBram Moolenaar 168071d4279SBram Moolenaarif !exists("*s:ParseRpmVars") 169071d4279SBram Moolenaar function s:ParseRpmVars(str, strline) 170071d4279SBram Moolenaar let end = -1 171071d4279SBram Moolenaar let ret = "" 172071d4279SBram Moolenaar while (1) 173071d4279SBram Moolenaar let start = match(a:str, "\%{", end+1) 1744072ba57SBram Moolenaar if start == -1 175071d4279SBram Moolenaar let ret = ret . strpart(a:str, end+1) 176071d4279SBram Moolenaar break 177071d4279SBram Moolenaar endif 178071d4279SBram Moolenaar let ret = ret . strpart(a:str, end+1, start-(end+1)) 179071d4279SBram Moolenaar let end = match(a:str, "}", start) 1804072ba57SBram Moolenaar if end == -1 181071d4279SBram Moolenaar let ret = ret . strpart(a:str, start) 182071d4279SBram Moolenaar break 183071d4279SBram Moolenaar endif 184071d4279SBram Moolenaar let varname = strpart(a:str, start+2, end-(start+2)) 185071d4279SBram Moolenaar execute a:strline 1861c6737b2SBram Moolenaar let definestr = "^[ \t]*%\\(define\\|global\\)[ \t]\\+".varname."[ \t]\\+\\(.*\\)$" 187071d4279SBram Moolenaar let linenum = search(definestr, "bW") 1884072ba57SBram Moolenaar if linenum != 0 1891c6737b2SBram Moolenaar let ret = ret . substitute(getline(linenum), definestr, "\\2", "") 190071d4279SBram Moolenaar endif 191071d4279SBram Moolenaar endwhile 192071d4279SBram Moolenaar return ret 193071d4279SBram Moolenaar endfunction 194071d4279SBram Moolenaarendif 195071d4279SBram Moolenaar 196071d4279SBram Moolenaar" The following lines, along with the macros/matchit.vim plugin, 197071d4279SBram Moolenaar" make it easy to navigate the different sections of a spec file 198071d4279SBram Moolenaar" with the % key (thanks to Max Ischenko). 199071d4279SBram Moolenaar 200071d4279SBram Moolenaarlet b:match_ignorecase = 0 201071d4279SBram Moolenaarlet b:match_words = 20282af8710SBram Moolenaar \ '^Name:^%description:^%clean:^%(?:auto)?setup:^%build:^%install:^%files:' . 203071d4279SBram Moolenaar \ '^%package:^%preun:^%postun:^%changelog' 204071d4279SBram Moolenaar 205b6b046b2SBram Moolenaarlet &cpo = s:cpo_save 206b6b046b2SBram Moolenaarunlet s:cpo_save 207b6b046b2SBram Moolenaar 20884f7235bSBram Moolenaarlet b:undo_ftplugin = "unlet! b:match_ignorecase b:match_words" 209