1*071d4279SBram Moolenaar" Vim filetype plugin file 2*071d4279SBram Moolenaar" Language: generic Changelog file 3*071d4279SBram Moolenaar" Maintainer: Nikolai Weibull <[email protected]> 4*071d4279SBram Moolenaar" URL: http://www.pcppopper.org/vim/ftplugin/pcp/changelog/ 5*071d4279SBram Moolenaar" Latest Revision: 2004-04-25 6*071d4279SBram Moolenaar" arch-tag: b00e2974-c559-4477-b7b2-3ef3f4061bdb 7*071d4279SBram Moolenaar" Variables: 8*071d4279SBram Moolenaar" g:changelog_timeformat - 9*071d4279SBram Moolenaar" description: the timeformat used in ChangeLog entries. 10*071d4279SBram Moolenaar" default: "%Y-%m-%d". 11*071d4279SBram Moolenaar" g:changelog_username - 12*071d4279SBram Moolenaar" description: the username to use in ChangeLog entries 13*071d4279SBram Moolenaar" default: try to deduce it from environment variables and system files. 14*071d4279SBram Moolenaar" Local Mappings: 15*071d4279SBram Moolenaar" <Leader>o - 16*071d4279SBram Moolenaar" adds a new changelog entry for the current user for the current date. 17*071d4279SBram Moolenaar" Global Mappings: 18*071d4279SBram Moolenaar" <Leader>o - 19*071d4279SBram Moolenaar" switches to the ChangeLog buffer opened for the current directory, or 20*071d4279SBram Moolenaar" opens it in a new buffer if it exists in the current directory. Then 21*071d4279SBram Moolenaar" it does the same as the local <Leader>o described above. 22*071d4279SBram Moolenaar" Notes: 23*071d4279SBram Moolenaar" run 'runtime ftplugin/changelog.vim' to enable the global mapping for 24*071d4279SBram Moolenaar" changelog files. 25*071d4279SBram Moolenaar" TODO: 26*071d4279SBram Moolenaar" should we perhaps open the ChangeLog file even if it doesn't exist already? 27*071d4279SBram Moolenaar" Problem is that you might end up with ChangeLog files all over the place. 28*071d4279SBram Moolenaar 29*071d4279SBram Moolenaar" If 'filetype' isn't "changelog", we must have been to add ChangeLog opener 30*071d4279SBram Moolenaarif &filetype == "changelog" 31*071d4279SBram Moolenaar " Only do this when not done yet for this buffer 32*071d4279SBram Moolenaar if exists("b:did_ftplugin") 33*071d4279SBram Moolenaar finish 34*071d4279SBram Moolenaar endif 35*071d4279SBram Moolenaar 36*071d4279SBram Moolenaar " Don't load another plugin for this buffer 37*071d4279SBram Moolenaar let b:did_ftplugin = 1 38*071d4279SBram Moolenaar 39*071d4279SBram Moolenaar let cpo_save = &cpo 40*071d4279SBram Moolenaar set cpo-=C 41*071d4279SBram Moolenaar 42*071d4279SBram Moolenaar " The format of the date-time field (should have been called dateformat) 43*071d4279SBram Moolenaar if !exists("g:changelog_timeformat") 44*071d4279SBram Moolenaar let g:changelog_timeformat = "%Y-%m-%d" 45*071d4279SBram Moolenaar endif 46*071d4279SBram Moolenaar 47*071d4279SBram Moolenaar " Try to figure out a reasonable username of the form: 48*071d4279SBram Moolenaar " Full Name <user@host> 49*071d4279SBram Moolenaar if !exists("g:changelog_username") 50*071d4279SBram Moolenaar if exists("$EMAIL_ADDRESS") 51*071d4279SBram Moolenaar let g:changelog_username = $EMAIL_ADDRESS 52*071d4279SBram Moolenaar elseif exists("$EMAIL") 53*071d4279SBram Moolenaar let g:changelog_username = $EMAIL 54*071d4279SBram Moolenaar else 55*071d4279SBram Moolenaar " Get the users login name 56*071d4279SBram Moolenaar let login = system('whoami') 57*071d4279SBram Moolenaar if v:shell_error 58*071d4279SBram Moolenaar let login = 'unknown' 59*071d4279SBram Moolenaar else 60*071d4279SBram Moolenaar let newline = stridx(login, "\n") 61*071d4279SBram Moolenaar if newline != -1 62*071d4279SBram Moolenaar let login = strpart(login, 0, newline) 63*071d4279SBram Moolenaar endif 64*071d4279SBram Moolenaar endif 65*071d4279SBram Moolenaar 66*071d4279SBram Moolenaar " Try to full name from gecos field in /etc/passwd 67*071d4279SBram Moolenaar if filereadable('/etc/passwd') 68*071d4279SBram Moolenaar let name = substitute( 69*071d4279SBram Moolenaar \system('cat /etc/passwd | grep ^`whoami`'), 70*071d4279SBram Moolenaar \'^\%([^:]*:\)\{4}\([^:]*\):.*$', '\1', '') 71*071d4279SBram Moolenaar endif 72*071d4279SBram Moolenaar 73*071d4279SBram Moolenaar " If there is no such file, or there was some other problem try 74*071d4279SBram Moolenaar " others 75*071d4279SBram Moolenaar if !filereadable('/etc/passwd') || v:shell_error 76*071d4279SBram Moolenaar " Maybe the environment has something of interest 77*071d4279SBram Moolenaar if exists("$NAME") 78*071d4279SBram Moolenaar let name = $NAME 79*071d4279SBram Moolenaar else 80*071d4279SBram Moolenaar " No? well, use the login name and capitalize first 81*071d4279SBram Moolenaar " character 82*071d4279SBram Moolenaar let name = toupper(login[0]) . strpart(login, 1) 83*071d4279SBram Moolenaar endif 84*071d4279SBram Moolenaar endif 85*071d4279SBram Moolenaar 86*071d4279SBram Moolenaar " Only keep stuff before the first comma 87*071d4279SBram Moolenaar let comma = stridx(name, ',') 88*071d4279SBram Moolenaar if comma != -1 89*071d4279SBram Moolenaar let name = strpart(name, 0, comma) 90*071d4279SBram Moolenaar endif 91*071d4279SBram Moolenaar 92*071d4279SBram Moolenaar " And substitute & in the real name with the login of our user 93*071d4279SBram Moolenaar let amp = stridx(name, '&') 94*071d4279SBram Moolenaar if amp != -1 95*071d4279SBram Moolenaar let name = strpart(name, 0, amp) . toupper(login[0]) . 96*071d4279SBram Moolenaar \strpart(login, 1) . strpart(name, amp + 1) 97*071d4279SBram Moolenaar endif 98*071d4279SBram Moolenaar 99*071d4279SBram Moolenaar " Get our hostname 100*071d4279SBram Moolenaar let hostname = system("hostname") 101*071d4279SBram Moolenaar if v:shell_error 102*071d4279SBram Moolenaar let hostname = 'unknownhost' 103*071d4279SBram Moolenaar else 104*071d4279SBram Moolenaar let newline = stridx(hostname, "\n") 105*071d4279SBram Moolenaar if newline != -1 106*071d4279SBram Moolenaar let hostname = strpart(hostname, 0, newline) 107*071d4279SBram Moolenaar endif 108*071d4279SBram Moolenaar endif 109*071d4279SBram Moolenaar 110*071d4279SBram Moolenaar " And finally set the username 111*071d4279SBram Moolenaar let g:changelog_username = name.' <'.login.'@'.hostname.'>' 112*071d4279SBram Moolenaar endif 113*071d4279SBram Moolenaar endif 114*071d4279SBram Moolenaar 115*071d4279SBram Moolenaar " Format used for new date-entries 116*071d4279SBram Moolenaar if !exists("g:changelog_new_date_format") 117*071d4279SBram Moolenaar let g:changelog_new_date_format = "%d %u\n\n\t* %c\n\n" 118*071d4279SBram Moolenaar endif 119*071d4279SBram Moolenaar 120*071d4279SBram Moolenaar " Format used for new entries to current date-entry 121*071d4279SBram Moolenaar if !exists("g:changelog_new_entry_format") 122*071d4279SBram Moolenaar let g:changelog_new_entry_format = "\t* %c" 123*071d4279SBram Moolenaar endif 124*071d4279SBram Moolenaar 125*071d4279SBram Moolenaar if !exists("g:changelog_date_entry_search") 126*071d4279SBram Moolenaar let g:changelog_date_entry_search = '^\s*%d\_s*%u' 127*071d4279SBram Moolenaar endif 128*071d4279SBram Moolenaar 129*071d4279SBram Moolenaar " Substitutes specific items in new date-entry formats and search strings 130*071d4279SBram Moolenaar " Can be done with substitute of course, but unclean, and need \@! then 131*071d4279SBram Moolenaar function! s:substitute_items(str, date, user) 132*071d4279SBram Moolenaar let str = a:str 133*071d4279SBram Moolenaar let i = stridx(str, '%') 134*071d4279SBram Moolenaar while i != -1 135*071d4279SBram Moolenaar let char = str[i + 1] 136*071d4279SBram Moolenaar if char == '%' 137*071d4279SBram Moolenaar let middle = '%' 138*071d4279SBram Moolenaar elseif char == 'd' 139*071d4279SBram Moolenaar let middle = a:date 140*071d4279SBram Moolenaar elseif char == 'u' 141*071d4279SBram Moolenaar let middle = a:user 142*071d4279SBram Moolenaar elseif char == 'c' 143*071d4279SBram Moolenaar let middle = '{cursor}' 144*071d4279SBram Moolenaar else 145*071d4279SBram Moolenaar let middle = char 146*071d4279SBram Moolenaar endif 147*071d4279SBram Moolenaar let str = strpart(str, 0, i) . middle . strpart(str, i + 2) 148*071d4279SBram Moolenaar let i = stridx(str, '%') 149*071d4279SBram Moolenaar endwhile 150*071d4279SBram Moolenaar return str 151*071d4279SBram Moolenaar endfunction 152*071d4279SBram Moolenaar 153*071d4279SBram Moolenaar function! s:position_cursor() 154*071d4279SBram Moolenaar if search('{cursor}') > 0 155*071d4279SBram Moolenaar let pos = line('.') 156*071d4279SBram Moolenaar let line = getline(pos) 157*071d4279SBram Moolenaar let cursor = stridx(line, '{cursor}') 158*071d4279SBram Moolenaar call setline(pos, substitute(line, '{cursor}', '', '')) 159*071d4279SBram Moolenaar endif 160*071d4279SBram Moolenaar startinsert! 161*071d4279SBram Moolenaar endfunction 162*071d4279SBram Moolenaar 163*071d4279SBram Moolenaar " Internal function to create a new entry in the ChangeLog 164*071d4279SBram Moolenaar function! s:new_changelog_entry() 165*071d4279SBram Moolenaar " Deal with 'paste' option 166*071d4279SBram Moolenaar let save_paste = &paste 167*071d4279SBram Moolenaar let &paste = 1 168*071d4279SBram Moolenaar 1 169*071d4279SBram Moolenaar " Look for an entry for today by our user 170*071d4279SBram Moolenaar let date = strftime(g:changelog_timeformat) 171*071d4279SBram Moolenaar let search = s:substitute_items(g:changelog_date_entry_search, date, 172*071d4279SBram Moolenaar \g:changelog_username) 173*071d4279SBram Moolenaar if search(search) > 0 174*071d4279SBram Moolenaar " Ok, now we look for the end of the date-entry, and add an entry 175*071d4279SBram Moolenaar let pos = nextnonblank(line('.') + 1) 176*071d4279SBram Moolenaar let line = getline(pos) 177*071d4279SBram Moolenaar while line =~ '^\s\+\S\+' 178*071d4279SBram Moolenaar let pos = pos + 1 179*071d4279SBram Moolenaar let line = getline(pos) 180*071d4279SBram Moolenaar endwhile 181*071d4279SBram Moolenaar let insert = s:substitute_items(g:changelog_new_entry_format, 182*071d4279SBram Moolenaar \'', '') 183*071d4279SBram Moolenaar execute "normal! ".(pos - 1)."Go".insert 184*071d4279SBram Moolenaar execute pos 185*071d4279SBram Moolenaar else 186*071d4279SBram Moolenaar " Flag for removing empty lines at end of new ChangeLogs 187*071d4279SBram Moolenaar let remove_empty = line('$') == 1 188*071d4279SBram Moolenaar 189*071d4279SBram Moolenaar " No entry today, so create a date-user header and insert an entry 190*071d4279SBram Moolenaar let todays_entry = s:substitute_items(g:changelog_new_date_format, 191*071d4279SBram Moolenaar \date, g:changelog_username) 192*071d4279SBram Moolenaar " Make sure we have a cursor positioning 193*071d4279SBram Moolenaar if stridx(todays_entry, '{cursor}') == -1 194*071d4279SBram Moolenaar let todays_entry = todays_entry.'{cursor}' 195*071d4279SBram Moolenaar endif 196*071d4279SBram Moolenaar 197*071d4279SBram Moolenaar " Now do the work 198*071d4279SBram Moolenaar execute "normal! i".todays_entry 199*071d4279SBram Moolenaar if remove_empty 200*071d4279SBram Moolenaar while getline('$') == '' 201*071d4279SBram Moolenaar $delete 202*071d4279SBram Moolenaar endwhile 203*071d4279SBram Moolenaar endif 204*071d4279SBram Moolenaar 205*071d4279SBram Moolenaar 1 206*071d4279SBram Moolenaar endif 207*071d4279SBram Moolenaar 208*071d4279SBram Moolenaar call s:position_cursor() 209*071d4279SBram Moolenaar 210*071d4279SBram Moolenaar " And reset 'paste' option 211*071d4279SBram Moolenaar let &paste = save_paste 212*071d4279SBram Moolenaar endfunction 213*071d4279SBram Moolenaar 214*071d4279SBram Moolenaar if exists(":NewChangelogEntry") != 2 215*071d4279SBram Moolenaar map <buffer> <silent> <Leader>o <Esc>:call <SID>new_changelog_entry()<CR> 216*071d4279SBram Moolenaar command! -nargs=0 NewChangelogEntry call s:new_changelog_entry() 217*071d4279SBram Moolenaar endif 218*071d4279SBram Moolenaar 219*071d4279SBram Moolenaar let b:undo_ftplugin = "setl com< tw< fo< et< ai<" 220*071d4279SBram Moolenaar 221*071d4279SBram Moolenaar if &textwidth == 0 222*071d4279SBram Moolenaar setlocal textwidth=78 223*071d4279SBram Moolenaar endif 224*071d4279SBram Moolenaar setlocal comments= 225*071d4279SBram Moolenaar setlocal formatoptions+=t 226*071d4279SBram Moolenaar setlocal noexpandtab 227*071d4279SBram Moolenaar setlocal autoindent 228*071d4279SBram Moolenaar 229*071d4279SBram Moolenaar let &cpo = cpo_save 230*071d4279SBram Moolenaarelse 231*071d4279SBram Moolenaar " Add the Changelog opening mapping 232*071d4279SBram Moolenaar nmap <silent> <Leader>o :call <SID>open_changelog()<CR> 233*071d4279SBram Moolenaar 234*071d4279SBram Moolenaar function! s:open_changelog() 235*071d4279SBram Moolenaar if filereadable('ChangeLog') 236*071d4279SBram Moolenaar if bufloaded('ChangeLog') 237*071d4279SBram Moolenaar let buf = bufnr('ChangeLog') 238*071d4279SBram Moolenaar execute "normal! \<C-W>t" 239*071d4279SBram Moolenaar while winbufnr(winnr()) != buf 240*071d4279SBram Moolenaar execute "normal! \<C-W>w" 241*071d4279SBram Moolenaar endwhile 242*071d4279SBram Moolenaar else 243*071d4279SBram Moolenaar split ChangeLog 244*071d4279SBram Moolenaar endif 245*071d4279SBram Moolenaar 246*071d4279SBram Moolenaar if exists("g:mapleader") 247*071d4279SBram Moolenaar execute "normal " . g:mapleader . "o" 248*071d4279SBram Moolenaar else 249*071d4279SBram Moolenaar execute "normal \\o" 250*071d4279SBram Moolenaar endif 251*071d4279SBram Moolenaar startinsert! 252*071d4279SBram Moolenaar endif 253*071d4279SBram Moolenaar endfunction 254*071d4279SBram Moolenaarendif 255*071d4279SBram Moolenaar 256*071d4279SBram Moolenaar" vim: set sts=2 sw=2: 257