spec.vim 5.7 KB

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