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