1071d4279SBram Moolenaar" Vim filetype plugin file 2071d4279SBram Moolenaar" Language: generic Changelog file 357657d85SBram Moolenaar" Maintainer: Nikolai Weibull <[email protected]> 4*2c7a7638SBram Moolenaar" Latest Revision: 2007-05-06 5071d4279SBram Moolenaar" Variables: 657657d85SBram Moolenaar" g:changelog_timeformat (deprecated: use g:changelog_dateformat instead) - 7071d4279SBram Moolenaar" description: the timeformat used in ChangeLog entries. 8071d4279SBram Moolenaar" default: "%Y-%m-%d". 957657d85SBram Moolenaar" g:changelog_dateformat - 1057657d85SBram Moolenaar" description: the format sent to strftime() to generate a date string. 1157657d85SBram Moolenaar" default: "%Y-%m-%d". 12071d4279SBram Moolenaar" g:changelog_username - 13071d4279SBram Moolenaar" description: the username to use in ChangeLog entries 14071d4279SBram Moolenaar" default: try to deduce it from environment variables and system files. 15071d4279SBram Moolenaar" Local Mappings: 16071d4279SBram Moolenaar" <Leader>o - 17071d4279SBram Moolenaar" adds a new changelog entry for the current user for the current date. 18071d4279SBram Moolenaar" Global Mappings: 19071d4279SBram Moolenaar" <Leader>o - 20071d4279SBram Moolenaar" switches to the ChangeLog buffer opened for the current directory, or 21071d4279SBram Moolenaar" opens it in a new buffer if it exists in the current directory. Then 22071d4279SBram Moolenaar" it does the same as the local <Leader>o described above. 23071d4279SBram Moolenaar" Notes: 24071d4279SBram Moolenaar" run 'runtime ftplugin/changelog.vim' to enable the global mapping for 25071d4279SBram Moolenaar" changelog files. 26071d4279SBram Moolenaar" TODO: 27071d4279SBram Moolenaar" should we perhaps open the ChangeLog file even if it doesn't exist already? 28071d4279SBram Moolenaar" Problem is that you might end up with ChangeLog files all over the place. 29071d4279SBram Moolenaar 30071d4279SBram Moolenaar" If 'filetype' isn't "changelog", we must have been to add ChangeLog opener 3157657d85SBram Moolenaarif &filetype == 'changelog' 3257657d85SBram Moolenaar if exists('b:did_ftplugin') 33071d4279SBram Moolenaar finish 34071d4279SBram Moolenaar endif 35071d4279SBram Moolenaar let b:did_ftplugin = 1 36071d4279SBram Moolenaar 3742eeac35SBram Moolenaar let s:cpo_save = &cpo 3842eeac35SBram Moolenaar set cpo&vim 39071d4279SBram Moolenaar 4057657d85SBram Moolenaar " Set up the format used for dates. 4157657d85SBram Moolenaar if !exists('g:changelog_dateformat') 4257657d85SBram Moolenaar if exists('g:changelog_timeformat') 4357657d85SBram Moolenaar let g:changelog_dateformat = g:changelog_timeformat 4457657d85SBram Moolenaar else 4557657d85SBram Moolenaar let g:changelog_dateformat = "%Y-%m-%d" 4657657d85SBram Moolenaar endif 47071d4279SBram Moolenaar endif 48071d4279SBram Moolenaar 49071d4279SBram Moolenaar " Try to figure out a reasonable username of the form: 5057657d85SBram Moolenaar " Full Name <user@host>. 5157657d85SBram Moolenaar if !exists('g:changelog_username') 5257657d85SBram Moolenaar if exists('$EMAIL') && $EMAIL != '' 53071d4279SBram Moolenaar let g:changelog_username = $EMAIL 5457657d85SBram Moolenaar elseif exists('$EMAIL_ADDRESS') && $EMAIL_ADDRESS != '' 5557657d85SBram Moolenaar " This is some Debian junk if I remember correctly. 5657657d85SBram Moolenaar let g:changelog_username = $EMAIL_ADDRESS 57071d4279SBram Moolenaar else 5857657d85SBram Moolenaar " Get the users login name. 59071d4279SBram Moolenaar let login = system('whoami') 60071d4279SBram Moolenaar if v:shell_error 61071d4279SBram Moolenaar let login = 'unknown' 62071d4279SBram Moolenaar else 63071d4279SBram Moolenaar let newline = stridx(login, "\n") 64071d4279SBram Moolenaar if newline != -1 65071d4279SBram Moolenaar let login = strpart(login, 0, newline) 66071d4279SBram Moolenaar endif 67071d4279SBram Moolenaar endif 68071d4279SBram Moolenaar 6957657d85SBram Moolenaar " Try to get the full name from gecos field in /etc/passwd. 70071d4279SBram Moolenaar if filereadable('/etc/passwd') 7157657d85SBram Moolenaar for line in readfile('/etc/passwd') 7257657d85SBram Moolenaar if line =~ '^' . login 7357657d85SBram Moolenaar let name = substitute(line,'^\%([^:]*:\)\{4}\([^:]*\):.*$','\1','') 7457657d85SBram Moolenaar " Only keep stuff before the first comma. 75071d4279SBram Moolenaar let comma = stridx(name, ',') 76071d4279SBram Moolenaar if comma != -1 77071d4279SBram Moolenaar let name = strpart(name, 0, comma) 78071d4279SBram Moolenaar endif 7957657d85SBram Moolenaar " And substitute & in the real name with the login of our user. 80071d4279SBram Moolenaar let amp = stridx(name, '&') 81071d4279SBram Moolenaar if amp != -1 82071d4279SBram Moolenaar let name = strpart(name, 0, amp) . toupper(login[0]) . 83071d4279SBram Moolenaar \ strpart(login, 1) . strpart(name, amp + 1) 84071d4279SBram Moolenaar endif 8557657d85SBram Moolenaar endif 8657657d85SBram Moolenaar endfor 8757657d85SBram Moolenaar endif 88071d4279SBram Moolenaar 8957657d85SBram Moolenaar " If we haven't found a name, try to gather it from other places. 9057657d85SBram Moolenaar if !exists('name') 9157657d85SBram Moolenaar " Maybe the environment has something of interest. 9257657d85SBram Moolenaar if exists("$NAME") 9357657d85SBram Moolenaar let name = $NAME 9457657d85SBram Moolenaar else 9557657d85SBram Moolenaar " No? well, use the login name and capitalize first 9657657d85SBram Moolenaar " character. 9757657d85SBram Moolenaar let name = toupper(login[0]) . strpart(login, 1) 9857657d85SBram Moolenaar endif 9957657d85SBram Moolenaar endif 10057657d85SBram Moolenaar 10157657d85SBram Moolenaar " Get our hostname. 10257657d85SBram Moolenaar let hostname = system('hostname') 103071d4279SBram Moolenaar if v:shell_error 10457657d85SBram Moolenaar let hostname = 'localhost' 105071d4279SBram Moolenaar else 106071d4279SBram Moolenaar let newline = stridx(hostname, "\n") 107071d4279SBram Moolenaar if newline != -1 108071d4279SBram Moolenaar let hostname = strpart(hostname, 0, newline) 109071d4279SBram Moolenaar endif 110071d4279SBram Moolenaar endif 111071d4279SBram Moolenaar 11257657d85SBram Moolenaar " And finally set the username. 113071d4279SBram Moolenaar let g:changelog_username = name . ' <' . login . '@' . hostname . '>' 114071d4279SBram Moolenaar endif 115071d4279SBram Moolenaar endif 116071d4279SBram Moolenaar 11757657d85SBram Moolenaar " Format used for new date entries. 11857657d85SBram Moolenaar if !exists('g:changelog_new_date_format') 119071d4279SBram Moolenaar let g:changelog_new_date_format = "%d %u\n\n\t* %c\n\n" 120071d4279SBram Moolenaar endif 121071d4279SBram Moolenaar 12257657d85SBram Moolenaar " Format used for new entries to current date entry. 12357657d85SBram Moolenaar if !exists('g:changelog_new_entry_format') 124071d4279SBram Moolenaar let g:changelog_new_entry_format = "\t* %c" 125071d4279SBram Moolenaar endif 126071d4279SBram Moolenaar 12757657d85SBram Moolenaar " Regular expression used to find a given date entry. 12857657d85SBram Moolenaar if !exists('g:changelog_date_entry_search') 129071d4279SBram Moolenaar let g:changelog_date_entry_search = '^\s*%d\_s*%u' 130071d4279SBram Moolenaar endif 131071d4279SBram Moolenaar 132*2c7a7638SBram Moolenaar " Regular expression used to find the end of a date entry 133*2c7a7638SBram Moolenaar if !exists('g:changelog_date_end_entry_search') 134*2c7a7638SBram Moolenaar let g:changelog_date_entry_search = '^\s*$' 135*2c7a7638SBram Moolenaar endif 136*2c7a7638SBram Moolenaar 137*2c7a7638SBram Moolenaar 13857657d85SBram Moolenaar " Substitutes specific items in new date-entry formats and search strings. 13957657d85SBram Moolenaar " Can be done with substitute of course, but unclean, and need \@! then. 140071d4279SBram Moolenaar function! s:substitute_items(str, date, user) 141071d4279SBram Moolenaar let str = a:str 14257657d85SBram Moolenaar let middles = {'%': '%', 'd': a:date, 'u': a:user, 'c': '{cursor}'} 143071d4279SBram Moolenaar let i = stridx(str, '%') 144071d4279SBram Moolenaar while i != -1 14557657d85SBram Moolenaar let inc = 0 14657657d85SBram Moolenaar if has_key(middles, str[i + 1]) 14757657d85SBram Moolenaar let mid = middles[str[i + 1]] 14857657d85SBram Moolenaar let str = strpart(str, 0, i) . mid . strpart(str, i + 2) 14957657d85SBram Moolenaar let inc = strlen(mid) 150071d4279SBram Moolenaar endif 15157657d85SBram Moolenaar let i = stridx(str, '%', i + 1 + inc) 152071d4279SBram Moolenaar endwhile 153071d4279SBram Moolenaar return str 154071d4279SBram Moolenaar endfunction 155071d4279SBram Moolenaar 15657657d85SBram Moolenaar " Position the cursor once we've done all the funky substitution. 157071d4279SBram Moolenaar function! s:position_cursor() 158071d4279SBram Moolenaar if search('{cursor}') > 0 15957657d85SBram Moolenaar let lnum = line('.') 16057657d85SBram Moolenaar let line = getline(lnum) 161071d4279SBram Moolenaar let cursor = stridx(line, '{cursor}') 16257657d85SBram Moolenaar call setline(lnum, substitute(line, '{cursor}', '', '')) 163071d4279SBram Moolenaar endif 164071d4279SBram Moolenaar startinsert! 165071d4279SBram Moolenaar endfunction 166071d4279SBram Moolenaar 16757657d85SBram Moolenaar " Internal function to create a new entry in the ChangeLog. 168071d4279SBram Moolenaar function! s:new_changelog_entry() 16957657d85SBram Moolenaar " Deal with 'paste' option. 170071d4279SBram Moolenaar let save_paste = &paste 171071d4279SBram Moolenaar let &paste = 1 17257657d85SBram Moolenaar call cursor(1, 1) 17357657d85SBram Moolenaar " Look for an entry for today by our user. 17457657d85SBram Moolenaar let date = strftime(g:changelog_dateformat) 175071d4279SBram Moolenaar let search = s:substitute_items(g:changelog_date_entry_search, date, 176071d4279SBram Moolenaar \ g:changelog_username) 177071d4279SBram Moolenaar if search(search) > 0 17857657d85SBram Moolenaar " Ok, now we look for the end of the date entry, and add an entry. 17957657d85SBram Moolenaar call cursor(nextnonblank(line('.') + 1), 1) 180*2c7a7638SBram Moolenaar if search(g:changelog_date_end_entry_search, 'W') > 0 18157657d85SBram Moolenaar let p = line('.') - 1 182071d4279SBram Moolenaar else 18357657d85SBram Moolenaar let p = line('.') 18457657d85SBram Moolenaar endif 18557657d85SBram Moolenaar let ls = split(s:substitute_items(g:changelog_new_entry_format, '', ''), 18657657d85SBram Moolenaar \ '\n') 18757657d85SBram Moolenaar call append(p, ls) 18857657d85SBram Moolenaar call cursor(p + 1, 1) 18957657d85SBram Moolenaar else 19057657d85SBram Moolenaar " Flag for removing empty lines at end of new ChangeLogs. 191071d4279SBram Moolenaar let remove_empty = line('$') == 1 192071d4279SBram Moolenaar 19357657d85SBram Moolenaar " No entry today, so create a date-user header and insert an entry. 194071d4279SBram Moolenaar let todays_entry = s:substitute_items(g:changelog_new_date_format, 195071d4279SBram Moolenaar \ date, g:changelog_username) 19657657d85SBram Moolenaar " Make sure we have a cursor positioning. 197071d4279SBram Moolenaar if stridx(todays_entry, '{cursor}') == -1 198071d4279SBram Moolenaar let todays_entry = todays_entry . '{cursor}' 199071d4279SBram Moolenaar endif 200071d4279SBram Moolenaar 20157657d85SBram Moolenaar " Now do the work. 20257657d85SBram Moolenaar call append(0, split(todays_entry, '\n')) 20357657d85SBram Moolenaar 20457657d85SBram Moolenaar " Remove empty lines at end of file. 205071d4279SBram Moolenaar if remove_empty 20657657d85SBram Moolenaar $-/^\s*$/-1,$delete 207071d4279SBram Moolenaar endif 208071d4279SBram Moolenaar 20957657d85SBram Moolenaar " Reposition cursor once we're done. 21057657d85SBram Moolenaar call cursor(1, 1) 211071d4279SBram Moolenaar endif 212071d4279SBram Moolenaar 213071d4279SBram Moolenaar call s:position_cursor() 214071d4279SBram Moolenaar 215071d4279SBram Moolenaar " And reset 'paste' option 216071d4279SBram Moolenaar let &paste = save_paste 217071d4279SBram Moolenaar endfunction 218071d4279SBram Moolenaar 219071d4279SBram Moolenaar if exists(":NewChangelogEntry") != 2 220071d4279SBram Moolenaar map <buffer> <silent> <Leader>o <Esc>:call <SID>new_changelog_entry()<CR> 221071d4279SBram Moolenaar command! -nargs=0 NewChangelogEntry call s:new_changelog_entry() 222071d4279SBram Moolenaar endif 223071d4279SBram Moolenaar 22457657d85SBram Moolenaar let b:undo_ftplugin = "setl com< fo< et< ai<" 225071d4279SBram Moolenaar 226071d4279SBram Moolenaar setlocal comments= 227071d4279SBram Moolenaar setlocal formatoptions+=t 228071d4279SBram Moolenaar setlocal noexpandtab 22942eeac35SBram Moolenaar setlocal autoindent 230071d4279SBram Moolenaar 23157657d85SBram Moolenaar if &textwidth == 0 23257657d85SBram Moolenaar setlocal textwidth=78 23357657d85SBram Moolenaar let b:undo_ftplugin .= " tw<" 23457657d85SBram Moolenaar endif 23557657d85SBram Moolenaar 23642eeac35SBram Moolenaar let &cpo = s:cpo_save 23742eeac35SBram Moolenaar unlet s:cpo_save 238071d4279SBram Moolenaarelse 239071d4279SBram Moolenaar " Add the Changelog opening mapping 240071d4279SBram Moolenaar nmap <silent> <Leader>o :call <SID>open_changelog()<CR> 241071d4279SBram Moolenaar 242071d4279SBram Moolenaar function! s:open_changelog() 24357657d85SBram Moolenaar if !filereadable('ChangeLog') 24457657d85SBram Moolenaar return 24557657d85SBram Moolenaar endif 246071d4279SBram Moolenaar let buf = bufnr('ChangeLog') 24757657d85SBram Moolenaar if buf != -1 24857657d85SBram Moolenaar if bufwinnr(buf) != -1 249*2c7a7638SBram Moolenaar execute bufwinnr(buf) . 'wincmd w' 25057657d85SBram Moolenaar else 251*2c7a7638SBram Moolenaar execute 'sbuffer' buf 25257657d85SBram Moolenaar endif 253071d4279SBram Moolenaar else 254071d4279SBram Moolenaar split ChangeLog 255071d4279SBram Moolenaar endif 256071d4279SBram Moolenaar 25757657d85SBram Moolenaar call s:new_changelog_entry() 258071d4279SBram Moolenaar endfunction 259071d4279SBram Moolenaarendif 260