runtime/ftplugin/debchangelog.vim
author James McCoy <jamessan@debian.org>
Sun Apr 29 17:01:58 2012 -0400 (2 weeks ago)
branchunstable
changeset 3701 ea14d575406a
parent 3512 03ce39be12d4
parent 3519 b7811ab264bf
permissions -rw-r--r--
Actually remove awk-shebang.patch
     1 " Vim filetype plugin file (GUI menu, folding and completion)
     2 " Language:     Debian Changelog
     3 " Maintainer:   Debian Vim Maintainers <pkg-vim-maintainers@lists.alioth.debian.org>
     4 " Former Maintainers:   Michael Piefel <piefel@informatik.hu-berlin.de>
     5 "                       Stefano Zacchiroli <zack@debian.org>
     6 " Last Change:  2012-01-31
     7 " License:      Vim License
     8 " URL:          http://hg.debian.org/hg/pkg-vim/vim/file/unstable/runtime/ftplugin/debchangelog.vim
     9 
    10 " Bug completion requires apt-listbugs installed for Debian packages or
    11 " python-launchpadlib installed for Ubuntu packages
    12 
    13 if exists("b:did_ftplugin")
    14   finish
    15 endif
    16 let b:did_ftplugin=1
    17 
    18 " {{{1 Local settings (do on every load)
    19 if exists("g:debchangelog_fold_enable")
    20   setlocal foldmethod=expr
    21   setlocal foldexpr=DebGetChangelogFold(v:lnum)
    22   setlocal foldtext=DebChangelogFoldText()
    23 endif
    24 
    25 " Debian changelogs are not supposed to have any other text width,
    26 " so the user cannot override this setting
    27 setlocal tw=78
    28 setlocal comments=f:* 
    29 
    30 " Clean unloading
    31 let b:undo_ftplugin = "setlocal tw< comments< foldmethod< foldexpr< foldtext<"
    32 " }}}1
    33 
    34 if exists("g:did_changelog_ftplugin")
    35   finish
    36 endif
    37 
    38 " Don't load another plugin (this is global)
    39 let g:did_changelog_ftplugin = 1
    40 
    41 " {{{1 GUI menu
    42 
    43 " 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?
    46 function <SID>FullName()
    47     if exists("$DEBFULLNAME")
    48 	return $DEBFULLNAME
    49     elseif exists("g:debianfullname")
    50 	return g:debianfullname
    51     else
    52 	return "Your Name"
    53     endif
    54 endfunction
    55 
    56 " Returns email address, from $DEBEMAIL, $EMAIL or debianemail.
    57 function <SID>Email()
    58     if exists("$DEBEMAIL")
    59 	return $DEBEMAIL
    60     elseif exists("$EMAIL")
    61 	return $EMAIL
    62     elseif exists("g:debianemail")
    63 	return g:debianemail
    64     else
    65 	return "your@email.address"
    66     endif
    67 endfunction
    68 
    69 " Returns date in RFC822 format.
    70 function <SID>Date()
    71     let savelang = v:lc_time
    72     execute "language time C"
    73     let dateandtime = strftime("%a, %d %b %Y %X %z")
    74     execute "language time " . savelang
    75     return dateandtime
    76 endfunction
    77 
    78 function <SID>WarnIfNotUnfinalised()
    79     if match(getline("."), " -- [[:alpha:]][[:alnum:].]")!=-1
    80 	echohl WarningMsg
    81 	echo "The entry has not been unfinalised before editing."
    82 	echohl None
    83 	return 1
    84     endif
    85     return 0
    86 endfunction
    87 
    88 function <SID>Finalised()
    89     let savelinenum = line(".")
    90     normal 1G
    91     call search("^ -- ")
    92     if match(getline("."), " -- [[:alpha:]][[:alnum:].]")!=-1
    93 	let returnvalue = 1
    94     else
    95 	let returnvalue = 0
    96     endif
    97     execute savelinenum
    98     return returnvalue
    99 endfunction
   100 
   101 " These functions implement the menus
   102 function 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
   111     call append(0, substitute(getline(1), '-\([[:digit:]]\+\))', '-$$\1)', ''))
   112     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 
   121     call setline(1, substitute(getline(1), '-\$\$', '-', ''))
   122     if exists("g:debchangelog_fold_enable")
   123         foldopen
   124     endif
   125     call AddEntry()
   126 endfunction
   127 
   128 function AddEntry()
   129     normal 1G
   130     call search("^ -- ")
   131     normal kk
   132     call append(".", "  * ")
   133     normal jjj
   134     let warn=<SID>WarnIfNotUnfinalised()
   135     normal kk
   136     if warn
   137 	echohl MoreMsg
   138 	call input("Hit ENTER")
   139 	echohl None
   140     endif
   141     startinsert!
   142 endfunction
   143 
   144 function CloseBug()
   145     normal 1G
   146     call search("^ -- ")
   147     let warn=<SID>WarnIfNotUnfinalised()
   148     normal kk
   149     call append(".", "  *  (closes: #" . input("Bug number to close: ") . ")")
   150     normal j^ll
   151     startinsert
   152 endfunction
   153 
   154 function Distribution(dist)
   155     call setline(1, substitute(getline(1), ") [[:lower:] ]*;", ") " . a:dist . ";", ""))
   156 endfunction
   157 
   158 function Urgency(urg)
   159     call setline(1, substitute(getline(1), "urgency=.*$", "urgency=" . a:urg, ""))
   160 endfunction
   161 
   162 function <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
   171 endfunction
   172 
   173 function Unfinalise()
   174     call <SID>UnfinaliseMenu()
   175     normal 1G
   176     call search("^ -- ")
   177     call setline(".", " -- ")
   178 endfunction
   179 
   180 function <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
   189 endfunction
   190 
   191 function Finalise()
   192     call <SID>FinaliseMenu()
   193     normal 1G
   194     call search("^ -- ")
   195     call setline(".", " -- " . <SID>FullName() . " <" . <SID>Email() . ">  " . <SID>Date())
   196 endfunction
   197 
   198 
   199 function <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
   227 endfunction
   228 
   229 augroup changelogMenu
   230 au BufEnter * if &filetype == "debchangelog" | call <SID>MakeMenu() | endif
   231 au BufLeave * if &filetype == "debchangelog" | silent! aunmenu Changelog | endif
   232 augroup END
   233 
   234 " }}}
   235 " {{{1 folding
   236 
   237 " look for an author name in the [zonestart zoneend] lines searching backward
   238 function! s:getAuthor(zonestart, zoneend)
   239   let linepos = a:zoneend
   240   while linepos >= a:zonestart
   241     let line = getline(linepos)
   242     if line =~ '^ --'
   243       return substitute(line, '^ --\s*\([^<]\+\)\s*.*', '\1', '')
   244     endif
   245     let linepos -= 1
   246   endwhile
   247   return '[unknown]'
   248 endfunction
   249 
   250 " 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
   252 function! DebGetPkgSrcName(lineno)
   253   let lineidx = a:lineno
   254   let pkgname = ''
   255   while lineidx > 0
   256     let curline = getline(lineidx)
   257     if curline =~ '^\S'
   258       let pkgname = matchlist(curline, '^\(\S\+\).*$')[1]
   259       break
   260     endif
   261     let lineidx = lineidx - 1
   262   endwhile
   263   return pkgname
   264 endfunction
   265 
   266 function! DebChangelogFoldText()
   267   if v:folddashes == '-'  " changelog entry fold
   268     return foldtext() . ' -- ' . s:getAuthor(v:foldstart, v:foldend) . ' '
   269   endif
   270   return foldtext()
   271 endfunction
   272 
   273 function! DebGetChangelogFold(lnum)
   274   let line = getline(a:lnum)
   275   if line =~ '^\w\+'
   276     return '>1' " beginning of a changelog entry
   277   endif
   278   if line =~ '^\s\+\[.*\]'
   279     return '>2' " beginning of an author-specific chunk
   280   endif
   281   if line =~ '^ --'
   282     return '1'
   283   endif
   284   return '='
   285 endfunction
   286 
   287 if exists("g:debchangelog_fold_enable")
   288   silent! foldopen!   " unfold the entry the cursor is on (usually the first one)
   289 endif
   290 
   291 " }}}
   292 
   293 " {{{1 omnicompletion for Closes: #
   294 
   295 if !exists('g:debchangelog_listbugs_severities')
   296   let g:debchangelog_listbugs_severities = 'critical,grave,serious,important,normal,minor,wishlist'
   297 endif
   298 
   299 fun! DebCompleteBugs(findstart, base)
   300   if a:findstart
   301     let line = getline('.')
   302 
   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 
   308     while try_colidx > 0 && line[try_colidx - 1] =~ '\s\|\d\|#\|,\|:'
   309       let try_colidx = try_colidx - 1
   310       if line[try_colidx] == '#' && colidx == -1
   311         " found hash, where we complete from:
   312         let colidx = try_colidx
   313       elseif line[try_colidx] == ':'
   314         if try_colidx > 1 && strpart(line, try_colidx - 2, 3) =~ '\clp:'
   315           let g:debchangelog_complete_mode = 'lp'
   316         endif
   317         break
   318       endif
   319     endwhile
   320     return colidx
   321   else " return matches:
   322     let bug_lines = []
   323     if g:debchangelog_complete_mode == 'lp'
   324       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
   330 import vim
   331 try:
   332     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
   350 except ImportError:
   351     vim.command('echoerr \'python-launchpadlib >= 1.5.4 needs to be installed to use Launchpad bug completion\'')
   352 EOF
   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')
   361     endif
   362     let completions = []
   363     for line in bug_lines
   364       let parts = matchlist(line, '^\s*\(#\S\+\)\s*-\s*\(.*\)$')
   365       " filter only those which match a:base:
   366       if parts[1] !~ "^" . a:base
   367         continue
   368       endif
   369       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
   377 endfun
   378 
   379 setlocal omnifunc=DebCompleteBugs
   380 
   381 " }}}
   382 
   383 " vim: set foldmethod=marker: