blob: a78f7811f19cd1a4697722c4ded6a10926c19715 [file] [log] [blame]
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00001" Vim filetype plugin file (GUI menu, folding and completion)
Bram Moolenaar00a927d2010-05-14 23:24:24 +02002" Language: Debian Changelog
Bram Moolenaar72540672018-02-09 22:00:53 +01003" Maintainer: Debian Vim Maintainers
Bram Moolenaar00a927d2010-05-14 23:24:24 +02004" Former Maintainers: Michael Piefel <piefel@informatik.hu-berlin.de>
5" Stefano Zacchiroli <zack@debian.org>
Bram Moolenaar85eee132018-05-06 17:57:30 +02006" Last Change: 2018-01-28
Bram Moolenaarb8ff1fb2012-02-04 21:59:01 +01007" License: Vim License
Bram Moolenaar72540672018-02-09 22:00:53 +01008" URL: https://salsa.debian.org/vim-team/vim-debian/blob/master/ftplugin/debchangelog.vim
Bram Moolenaarbd2ac7e2006-04-28 22:34:45 +00009
Bram Moolenaarc236c162008-07-13 17:41:49 +000010" Bug completion requires apt-listbugs installed for Debian packages or
Bram Moolenaar00a927d2010-05-14 23:24:24 +020011" python-launchpadlib installed for Ubuntu packages
Bram Moolenaarc236c162008-07-13 17:41:49 +000012
Bram Moolenaar85eee132018-05-06 17:57:30 +020013if exists('b:did_ftplugin')
Bram Moolenaarbd2ac7e2006-04-28 22:34:45 +000014 finish
15endif
Bram Moolenaar9964e462007-05-05 17:54:07 +000016let b:did_ftplugin=1
Bram Moolenaarbd2ac7e2006-04-28 22:34:45 +000017
18" {{{1 Local settings (do on every load)
Bram Moolenaar85eee132018-05-06 17:57:30 +020019if exists('g:debchangelog_fold_enable')
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000020 setlocal foldmethod=expr
21 setlocal foldexpr=DebGetChangelogFold(v:lnum)
22 setlocal foldtext=DebChangelogFoldText()
23endif
Bram Moolenaarbd2ac7e2006-04-28 22:34:45 +000024
25" Debian changelogs are not supposed to have any other text width,
26" so the user cannot override this setting
27setlocal tw=78
28setlocal comments=f:*
29
30" Clean unloading
Bram Moolenaar85eee132018-05-06 17:57:30 +020031let b:undo_ftplugin = 'setlocal tw< comments< foldmethod< foldexpr< foldtext<'
Bram Moolenaarbd2ac7e2006-04-28 22:34:45 +000032" }}}1
Bram Moolenaar071d4272004-06-13 20:20:40 +000033
Bram Moolenaar85eee132018-05-06 17:57:30 +020034if exists('g:did_changelog_ftplugin')
Bram Moolenaar071d4272004-06-13 20:20:40 +000035 finish
36endif
37
38" Don't load another plugin (this is global)
39let g:did_changelog_ftplugin = 1
40
Bram Moolenaarf193fff2006-04-27 00:02:13 +000041" {{{1 GUI menu
42
Bram Moolenaar071d4272004-06-13 20:20:40 +000043" Helper functions returning various data.
44" Returns full name, either from $DEBFULLNAME or debianfullname.
45" TODO Is there a way to determine name from anywhere else?
46function <SID>FullName()
Bram Moolenaar85eee132018-05-06 17:57:30 +020047 if exists('$DEBFULLNAME')
Bram Moolenaar071d4272004-06-13 20:20:40 +000048 return $DEBFULLNAME
Bram Moolenaar85eee132018-05-06 17:57:30 +020049 elseif exists('g:debianfullname')
Bram Moolenaar071d4272004-06-13 20:20:40 +000050 return g:debianfullname
51 else
Bram Moolenaar85eee132018-05-06 17:57:30 +020052 return 'Your Name'
Bram Moolenaar071d4272004-06-13 20:20:40 +000053 endif
54endfunction
55
56" Returns email address, from $DEBEMAIL, $EMAIL or debianemail.
57function <SID>Email()
Bram Moolenaar85eee132018-05-06 17:57:30 +020058 if exists('$DEBEMAIL')
Bram Moolenaar071d4272004-06-13 20:20:40 +000059 return $DEBEMAIL
Bram Moolenaar85eee132018-05-06 17:57:30 +020060 elseif exists('$EMAIL')
Bram Moolenaar071d4272004-06-13 20:20:40 +000061 return $EMAIL
Bram Moolenaar85eee132018-05-06 17:57:30 +020062 elseif exists('g:debianemail')
Bram Moolenaarae5bce12005-08-15 21:41:48 +000063 return g:debianemail
Bram Moolenaar071d4272004-06-13 20:20:40 +000064 else
Bram Moolenaar85eee132018-05-06 17:57:30 +020065 return 'your@email.address'
Bram Moolenaar071d4272004-06-13 20:20:40 +000066 endif
67endfunction
68
69" Returns date in RFC822 format.
70function <SID>Date()
71 let savelang = v:lc_time
Bram Moolenaar85eee132018-05-06 17:57:30 +020072 execute 'language time C'
73 let dateandtime = strftime('%a, %d %b %Y %X %z')
74 execute 'language time ' . savelang
Bram Moolenaar071d4272004-06-13 20:20:40 +000075 return dateandtime
76endfunction
77
78function <SID>WarnIfNotUnfinalised()
Bram Moolenaar85eee132018-05-06 17:57:30 +020079 if match(getline('.'), ' -- [[:alpha:]][[:alnum:].]')!=-1
Bram Moolenaar071d4272004-06-13 20:20:40 +000080 echohl WarningMsg
Bram Moolenaar85eee132018-05-06 17:57:30 +020081 echo 'The entry has not been unfinalised before editing.'
Bram Moolenaar071d4272004-06-13 20:20:40 +000082 echohl None
83 return 1
84 endif
85 return 0
86endfunction
87
88function <SID>Finalised()
Bram Moolenaar85eee132018-05-06 17:57:30 +020089 let savelinenum = line('.')
90 1
91 call search('^ -- ')
92 if match(getline('.'), ' -- [[:alpha:]][[:alnum:].]')!=-1
Bram Moolenaar071d4272004-06-13 20:20:40 +000093 let returnvalue = 1
94 else
95 let returnvalue = 0
96 endif
97 execute savelinenum
98 return returnvalue
99endfunction
100
101" These functions implement the menus
102function NewVersion()
103 " The new entry is unfinalised and shall be changed
104 amenu disable Changelog.New\ Version
105 amenu enable Changelog.Add\ Entry
106 amenu enable Changelog.Close\ Bug
107 amenu enable Changelog.Set\ Distribution
108 amenu enable Changelog.Set\ Urgency
109 amenu disable Changelog.Unfinalise
110 amenu enable Changelog.Finalise
Bram Moolenaarbd2ac7e2006-04-28 22:34:45 +0000111 call append(0, substitute(getline(1), '-\([[:digit:]]\+\))', '-$$\1)', ''))
Bram Moolenaar85eee132018-05-06 17:57:30 +0200112 call append(1, '')
113 call append(2, '')
114 call append(3, ' -- ')
115 call append(4, '')
116 call Urgency('low')
117 normal! 1G0
118 call search(')')
119 normal! h
120 normal! 
Bram Moolenaarbd2ac7e2006-04-28 22:34:45 +0000121 call setline(1, substitute(getline(1), '-\$\$', '-', ''))
Bram Moolenaar85eee132018-05-06 17:57:30 +0200122 if exists('g:debchangelog_fold_enable')
Bram Moolenaarc236c162008-07-13 17:41:49 +0000123 foldopen
124 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000125 call AddEntry()
126endfunction
127
128function AddEntry()
Bram Moolenaar85eee132018-05-06 17:57:30 +0200129 1
130 call search('^ -- ')
131 .-2
132 call append('.', ' * ')
133 .+3
Bram Moolenaar071d4272004-06-13 20:20:40 +0000134 let warn=<SID>WarnIfNotUnfinalised()
Bram Moolenaar85eee132018-05-06 17:57:30 +0200135 .-2
Bram Moolenaar071d4272004-06-13 20:20:40 +0000136 if warn
137 echohl MoreMsg
Bram Moolenaar85eee132018-05-06 17:57:30 +0200138 call input('Hit ENTER')
Bram Moolenaar071d4272004-06-13 20:20:40 +0000139 echohl None
140 endif
141 startinsert!
142endfunction
143
144function CloseBug()
Bram Moolenaar85eee132018-05-06 17:57:30 +0200145 1
146 call search('^ -- ')
Bram Moolenaar071d4272004-06-13 20:20:40 +0000147 let warn=<SID>WarnIfNotUnfinalised()
Bram Moolenaar85eee132018-05-06 17:57:30 +0200148 .-2
149 call append('.', ' * (closes: #' . input('Bug number to close: ') . ')')
150 normal! j^ll
Bram Moolenaar071d4272004-06-13 20:20:40 +0000151 startinsert
152endfunction
153
154function Distribution(dist)
Bram Moolenaar85eee132018-05-06 17:57:30 +0200155 call setline(1, substitute(getline(1), ') *\%(UNRELEASED\|\l\+\);', ') ' . a:dist . ';', ''))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000156endfunction
157
158function Urgency(urg)
Bram Moolenaar85eee132018-05-06 17:57:30 +0200159 call setline(1, substitute(getline(1), 'urgency=.*$', 'urgency=' . a:urg, ''))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000160endfunction
161
162function <SID>UnfinaliseMenu()
163 " This means the entry shall be changed
164 amenu disable Changelog.New\ Version
165 amenu enable Changelog.Add\ Entry
166 amenu enable Changelog.Close\ Bug
167 amenu enable Changelog.Set\ Distribution
168 amenu enable Changelog.Set\ Urgency
169 amenu disable Changelog.Unfinalise
170 amenu enable Changelog.Finalise
171endfunction
172
173function Unfinalise()
174 call <SID>UnfinaliseMenu()
Bram Moolenaar85eee132018-05-06 17:57:30 +0200175 1
176 call search('^ -- ')
177 call setline('.', ' -- ')
Bram Moolenaar071d4272004-06-13 20:20:40 +0000178endfunction
179
180function <SID>FinaliseMenu()
181 " This means the entry should not be changed anymore
182 amenu enable Changelog.New\ Version
183 amenu disable Changelog.Add\ Entry
184 amenu disable Changelog.Close\ Bug
185 amenu disable Changelog.Set\ Distribution
186 amenu disable Changelog.Set\ Urgency
187 amenu enable Changelog.Unfinalise
188 amenu disable Changelog.Finalise
189endfunction
190
191function Finalise()
192 call <SID>FinaliseMenu()
Bram Moolenaar85eee132018-05-06 17:57:30 +0200193 1
194 call search('^ -- ')
195 call setline('.', ' -- ' . <SID>FullName() . ' <' . <SID>Email() . '> ' . <SID>Date())
Bram Moolenaar071d4272004-06-13 20:20:40 +0000196endfunction
197
198
199function <SID>MakeMenu()
200 amenu &Changelog.&New\ Version :call NewVersion()<CR>
201 amenu Changelog.&Add\ Entry :call AddEntry()<CR>
202 amenu Changelog.&Close\ Bug :call CloseBug()<CR>
203 menu Changelog.-sep- <nul>
204
205 amenu Changelog.Set\ &Distribution.&unstable :call Distribution("unstable")<CR>
206 amenu Changelog.Set\ Distribution.&frozen :call Distribution("frozen")<CR>
207 amenu Changelog.Set\ Distribution.&stable :call Distribution("stable")<CR>
208 menu Changelog.Set\ Distribution.-sep- <nul>
209 amenu Changelog.Set\ Distribution.frozen\ unstable :call Distribution("frozen unstable")<CR>
210 amenu Changelog.Set\ Distribution.stable\ unstable :call Distribution("stable unstable")<CR>
211 amenu Changelog.Set\ Distribution.stable\ frozen :call Distribution("stable frozen")<CR>
212 amenu Changelog.Set\ Distribution.stable\ frozen\ unstable :call Distribution("stable frozen unstable")<CR>
213
214 amenu Changelog.Set\ &Urgency.&low :call Urgency("low")<CR>
215 amenu Changelog.Set\ Urgency.&medium :call Urgency("medium")<CR>
216 amenu Changelog.Set\ Urgency.&high :call Urgency("high")<CR>
217
218 menu Changelog.-sep- <nul>
219 amenu Changelog.U&nfinalise :call Unfinalise()<CR>
220 amenu Changelog.&Finalise :call Finalise()<CR>
221
222 if <SID>Finalised()
223 call <SID>FinaliseMenu()
224 else
225 call <SID>UnfinaliseMenu()
226 endif
227endfunction
228
229augroup changelogMenu
230au BufEnter * if &filetype == "debchangelog" | call <SID>MakeMenu() | endif
Bram Moolenaare06c1882010-07-21 22:05:20 +0200231au BufLeave * if &filetype == "debchangelog" | silent! aunmenu Changelog | endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000232augroup END
233
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000234" }}}
235" {{{1 folding
236
Bram Moolenaar9964e462007-05-05 17:54:07 +0000237" look for an author name in the [zonestart zoneend] lines searching backward
238function! s:getAuthor(zonestart, zoneend)
239 let linepos = a:zoneend
240 while linepos >= a:zonestart
241 let line = getline(linepos)
Bram Moolenaar85eee132018-05-06 17:57:30 +0200242 if line =~# '^ --'
Bram Moolenaar9964e462007-05-05 17:54:07 +0000243 return substitute(line, '^ --\s*\([^<]\+\)\s*.*', '\1', '')
244 endif
245 let linepos -= 1
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000246 endwhile
Bram Moolenaar9964e462007-05-05 17:54:07 +0000247 return '[unknown]'
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000248endfunction
249
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000250" Look for a package source name searching backward from the givenline and
251" returns it. Return the empty string if the package name can't be found
252function! DebGetPkgSrcName(lineno)
253 let lineidx = a:lineno
254 let pkgname = ''
255 while lineidx > 0
256 let curline = getline(lineidx)
Bram Moolenaar85eee132018-05-06 17:57:30 +0200257 if curline =~# '^\S'
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000258 let pkgname = matchlist(curline, '^\(\S\+\).*$')[1]
259 break
260 endif
261 let lineidx = lineidx - 1
262 endwhile
263 return pkgname
264endfunction
265
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000266function! DebChangelogFoldText()
Bram Moolenaar85eee132018-05-06 17:57:30 +0200267 if v:folddashes ==# '-' " changelog entry fold
Bram Moolenaar9964e462007-05-05 17:54:07 +0000268 return foldtext() . ' -- ' . s:getAuthor(v:foldstart, v:foldend) . ' '
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000269 endif
270 return foldtext()
271endfunction
272
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000273function! DebGetChangelogFold(lnum)
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000274 let line = getline(a:lnum)
Bram Moolenaar85eee132018-05-06 17:57:30 +0200275 if line =~# '^\w\+'
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000276 return '>1' " beginning of a changelog entry
277 endif
Bram Moolenaar85eee132018-05-06 17:57:30 +0200278 if line =~# '^\s\+\[.*\]'
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000279 return '>2' " beginning of an author-specific chunk
280 endif
Bram Moolenaar85eee132018-05-06 17:57:30 +0200281 if line =~# '^ --'
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000282 return '1'
283 endif
284 return '='
285endfunction
286
Bram Moolenaar85eee132018-05-06 17:57:30 +0200287if exists('g:debchangelog_fold_enable')
Bram Moolenaarc236c162008-07-13 17:41:49 +0000288 silent! foldopen! " unfold the entry the cursor is on (usually the first one)
289endif
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000290
291" }}}
292
293" {{{1 omnicompletion for Closes: #
294
295if !exists('g:debchangelog_listbugs_severities')
296 let g:debchangelog_listbugs_severities = 'critical,grave,serious,important,normal,minor,wishlist'
297endif
298
299fun! DebCompleteBugs(findstart, base)
300 if a:findstart
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000301 let line = getline('.')
Bram Moolenaarc236c162008-07-13 17:41:49 +0000302
303 " try to detect whether this is closes: or lp:
304 let g:debchangelog_complete_mode = 'debbugs'
305 let try_colidx = col('.') - 1
306 let colidx = -1 " default to no-completion-possible
307
Bram Moolenaar85eee132018-05-06 17:57:30 +0200308 while try_colidx > 0 && line[try_colidx - 1] =~# '\s\|\d\|#\|,\|:'
Bram Moolenaarc236c162008-07-13 17:41:49 +0000309 let try_colidx = try_colidx - 1
Bram Moolenaar85eee132018-05-06 17:57:30 +0200310 if line[try_colidx] ==# '#' && colidx == -1
Bram Moolenaarc236c162008-07-13 17:41:49 +0000311 " found hash, where we complete from:
312 let colidx = try_colidx
Bram Moolenaar85eee132018-05-06 17:57:30 +0200313 elseif line[try_colidx] ==# ':'
314 if try_colidx > 1 && strpart(line, try_colidx - 2, 3) =~? '\clp:'
Bram Moolenaarc236c162008-07-13 17:41:49 +0000315 let g:debchangelog_complete_mode = 'lp'
316 endif
317 break
318 endif
319 endwhile
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000320 return colidx
Bram Moolenaarc236c162008-07-13 17:41:49 +0000321 else " return matches:
322 let bug_lines = []
Bram Moolenaar85eee132018-05-06 17:57:30 +0200323 if g:debchangelog_complete_mode ==? 'lp'
Bram Moolenaarc236c162008-07-13 17:41:49 +0000324 if ! has('python')
325 echoerr 'vim must be built with Python support to use LP bug completion'
326 return
327 endif
328 let pkgsrc = DebGetPkgSrcName(line('.'))
329 python << EOF
330import vim
331try:
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200332 from launchpadlib.launchpad import Launchpad
333 from lazr.restfulclient.errors import HTTPError
334 # login anonymously
335 lp = Launchpad.login_anonymously('debchangelog.vim', 'production')
336 ubuntu = lp.distributions['ubuntu']
337 try:
338 sp = ubuntu.getSourcePackage(name=vim.eval('pkgsrc'))
339 status = ('New', 'Incomplete', 'Confirmed', 'Triaged',
340 'In Progress', 'Fix Committed')
341 tasklist = sp.searchTasks(status=status, order_by='id')
342 liststr = '['
343 for task in tasklist:
344 bug = task.bug
345 liststr += "'#%d - %s'," % (bug.id, bug.title.replace('\'', '\'\''))
346 liststr += ']'
347 vim.command('silent let bug_lines = %s' % liststr.encode('utf-8'))
348 except HTTPError:
349 pass
Bram Moolenaarc236c162008-07-13 17:41:49 +0000350except ImportError:
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200351 vim.command('echoerr \'python-launchpadlib >= 1.5.4 needs to be installed to use Launchpad bug completion\'')
Bram Moolenaarc236c162008-07-13 17:41:49 +0000352EOF
353 else
354 if ! filereadable('/usr/sbin/apt-listbugs')
355 echoerr 'apt-listbugs not found, you should install it to use Closes bug completion'
356 return
357 endif
358 let pkgsrc = DebGetPkgSrcName(line('.'))
359 let listbugs_output = system('/usr/sbin/apt-listbugs -s ' . g:debchangelog_listbugs_severities . ' list ' . pkgsrc . ' | grep "^ #" 2> /dev/null')
360 let bug_lines = split(listbugs_output, '\n')
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000361 endif
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000362 let completions = []
363 for line in bug_lines
364 let parts = matchlist(line, '^\s*\(#\S\+\)\s*-\s*\(.*\)$')
Bram Moolenaarc236c162008-07-13 17:41:49 +0000365 " filter only those which match a:base:
Bram Moolenaar85eee132018-05-06 17:57:30 +0200366 if parts[1] !~ '^' . a:base
Bram Moolenaarc236c162008-07-13 17:41:49 +0000367 continue
368 endif
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000369 let completion = {}
370 let completion['word'] = parts[1]
371 let completion['menu'] = parts[2]
372 let completion['info'] = parts[0]
373 let completions += [completion]
374 endfor
375 return completions
376 endif
377endfun
378
379setlocal omnifunc=DebCompleteBugs
Bram Moolenaar9964e462007-05-05 17:54:07 +0000380
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000381" }}}
382
383" vim: set foldmethod=marker: