spec.vim 5.7 KB

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