1071d4279SBram Moolenaar" Vim filetype plugin file 2071d4279SBram Moolenaar" Language: generic Changelog file 3*42eeac35SBram Moolenaar" Maintainer: Nikolai Weibull <[email protected]> 4*42eeac35SBram Moolenaar" Latest Revision: 2005-06-29 5071d4279SBram Moolenaar" Variables: 6071d4279SBram Moolenaar" g:changelog_timeformat - 7071d4279SBram Moolenaar" description: the timeformat used in ChangeLog entries. 8071d4279SBram Moolenaar" default: "%Y-%m-%d". 9071d4279SBram Moolenaar" g:changelog_username - 10071d4279SBram Moolenaar" description: the username to use in ChangeLog entries 11071d4279SBram Moolenaar" default: try to deduce it from environment variables and system files. 12071d4279SBram Moolenaar" Local Mappings: 13071d4279SBram Moolenaar" <Leader>o - 14071d4279SBram Moolenaar" adds a new changelog entry for the current user for the current date. 15071d4279SBram Moolenaar" Global Mappings: 16071d4279SBram Moolenaar" <Leader>o - 17071d4279SBram Moolenaar" switches to the ChangeLog buffer opened for the current directory, or 18071d4279SBram Moolenaar" opens it in a new buffer if it exists in the current directory. Then 19071d4279SBram Moolenaar" it does the same as the local <Leader>o described above. 20071d4279SBram Moolenaar" Notes: 21071d4279SBram Moolenaar" run 'runtime ftplugin/changelog.vim' to enable the global mapping for 22071d4279SBram Moolenaar" changelog files. 23071d4279SBram Moolenaar" TODO: 24071d4279SBram Moolenaar" should we perhaps open the ChangeLog file even if it doesn't exist already? 25071d4279SBram Moolenaar" Problem is that you might end up with ChangeLog files all over the place. 26071d4279SBram Moolenaar 27071d4279SBram Moolenaar" If 'filetype' isn't "changelog", we must have been to add ChangeLog opener 28071d4279SBram Moolenaarif &filetype == "changelog" 29071d4279SBram Moolenaar if exists("b:did_ftplugin") 30071d4279SBram Moolenaar finish 31071d4279SBram Moolenaar endif 32071d4279SBram Moolenaar let b:did_ftplugin = 1 33071d4279SBram Moolenaar 34*42eeac35SBram Moolenaar let s:cpo_save = &cpo 35*42eeac35SBram Moolenaar set cpo&vim 36071d4279SBram Moolenaar 37071d4279SBram Moolenaar " The format of the date-time field (should have been called dateformat) 38071d4279SBram Moolenaar if !exists("g:changelog_timeformat") 39071d4279SBram Moolenaar let g:changelog_timeformat = "%Y-%m-%d" 40071d4279SBram Moolenaar endif 41071d4279SBram Moolenaar 42071d4279SBram Moolenaar " Try to figure out a reasonable username of the form: 43071d4279SBram Moolenaar " Full Name <user@host> 44071d4279SBram Moolenaar if !exists("g:changelog_username") 45071d4279SBram Moolenaar if exists("$EMAIL_ADDRESS") 46071d4279SBram Moolenaar let g:changelog_username = $EMAIL_ADDRESS 47071d4279SBram Moolenaar elseif exists("$EMAIL") 48071d4279SBram Moolenaar let g:changelog_username = $EMAIL 49071d4279SBram Moolenaar else 50071d4279SBram Moolenaar " Get the users login name 51071d4279SBram Moolenaar let login = system('whoami') 52071d4279SBram Moolenaar if v:shell_error 53071d4279SBram Moolenaar let login = 'unknown' 54071d4279SBram Moolenaar else 55071d4279SBram Moolenaar let newline = stridx(login, "\n") 56071d4279SBram Moolenaar if newline != -1 57071d4279SBram Moolenaar let login = strpart(login, 0, newline) 58071d4279SBram Moolenaar endif 59071d4279SBram Moolenaar endif 60071d4279SBram Moolenaar 61071d4279SBram Moolenaar " Try to full name from gecos field in /etc/passwd 62071d4279SBram Moolenaar if filereadable('/etc/passwd') 63071d4279SBram Moolenaar let name = substitute( 64071d4279SBram Moolenaar \system('cat /etc/passwd | grep ^`whoami`'), 65071d4279SBram Moolenaar \'^\%([^:]*:\)\{4}\([^:]*\):.*$', '\1', '') 66071d4279SBram Moolenaar endif 67071d4279SBram Moolenaar 68071d4279SBram Moolenaar " If there is no such file, or there was some other problem try 69071d4279SBram Moolenaar " others 70071d4279SBram Moolenaar if !filereadable('/etc/passwd') || v:shell_error 71071d4279SBram Moolenaar " Maybe the environment has something of interest 72071d4279SBram Moolenaar if exists("$NAME") 73071d4279SBram Moolenaar let name = $NAME 74071d4279SBram Moolenaar else 75071d4279SBram Moolenaar " No? well, use the login name and capitalize first 76071d4279SBram Moolenaar " character 77071d4279SBram Moolenaar let name = toupper(login[0]) . strpart(login, 1) 78071d4279SBram Moolenaar endif 79071d4279SBram Moolenaar endif 80071d4279SBram Moolenaar 81071d4279SBram Moolenaar " Only keep stuff before the first comma 82071d4279SBram Moolenaar let comma = stridx(name, ',') 83071d4279SBram Moolenaar if comma != -1 84071d4279SBram Moolenaar let name = strpart(name, 0, comma) 85071d4279SBram Moolenaar endif 86071d4279SBram Moolenaar 87071d4279SBram Moolenaar " And substitute & in the real name with the login of our user 88071d4279SBram Moolenaar let amp = stridx(name, '&') 89071d4279SBram Moolenaar if amp != -1 90071d4279SBram Moolenaar let name = strpart(name, 0, amp) . toupper(login[0]) . 91071d4279SBram Moolenaar \strpart(login, 1) . strpart(name, amp + 1) 92071d4279SBram Moolenaar endif 93071d4279SBram Moolenaar 94071d4279SBram Moolenaar " Get our hostname 95071d4279SBram Moolenaar let hostname = system("hostname") 96071d4279SBram Moolenaar if v:shell_error 97071d4279SBram Moolenaar let hostname = 'unknownhost' 98071d4279SBram Moolenaar else 99071d4279SBram Moolenaar let newline = stridx(hostname, "\n") 100071d4279SBram Moolenaar if newline != -1 101071d4279SBram Moolenaar let hostname = strpart(hostname, 0, newline) 102071d4279SBram Moolenaar endif 103071d4279SBram Moolenaar endif 104071d4279SBram Moolenaar 105071d4279SBram Moolenaar " And finally set the username 106071d4279SBram Moolenaar let g:changelog_username = name.' <'.login.'@'.hostname.'>' 107071d4279SBram Moolenaar endif 108071d4279SBram Moolenaar endif 109071d4279SBram Moolenaar 110071d4279SBram Moolenaar " Format used for new date-entries 111071d4279SBram Moolenaar if !exists("g:changelog_new_date_format") 112071d4279SBram Moolenaar let g:changelog_new_date_format = "%d %u\n\n\t* %c\n\n" 113071d4279SBram Moolenaar endif 114071d4279SBram Moolenaar 115071d4279SBram Moolenaar " Format used for new entries to current date-entry 116071d4279SBram Moolenaar if !exists("g:changelog_new_entry_format") 117071d4279SBram Moolenaar let g:changelog_new_entry_format = "\t* %c" 118071d4279SBram Moolenaar endif 119071d4279SBram Moolenaar 120071d4279SBram Moolenaar if !exists("g:changelog_date_entry_search") 121071d4279SBram Moolenaar let g:changelog_date_entry_search = '^\s*%d\_s*%u' 122071d4279SBram Moolenaar endif 123071d4279SBram Moolenaar 124071d4279SBram Moolenaar " Substitutes specific items in new date-entry formats and search strings 125071d4279SBram Moolenaar " Can be done with substitute of course, but unclean, and need \@! then 126071d4279SBram Moolenaar function! s:substitute_items(str, date, user) 127071d4279SBram Moolenaar let str = a:str 128071d4279SBram Moolenaar let i = stridx(str, '%') 129071d4279SBram Moolenaar while i != -1 130071d4279SBram Moolenaar let char = str[i + 1] 131071d4279SBram Moolenaar if char == '%' 132071d4279SBram Moolenaar let middle = '%' 133071d4279SBram Moolenaar elseif char == 'd' 134071d4279SBram Moolenaar let middle = a:date 135071d4279SBram Moolenaar elseif char == 'u' 136071d4279SBram Moolenaar let middle = a:user 137071d4279SBram Moolenaar elseif char == 'c' 138071d4279SBram Moolenaar let middle = '{cursor}' 139071d4279SBram Moolenaar else 140071d4279SBram Moolenaar let middle = char 141071d4279SBram Moolenaar endif 142071d4279SBram Moolenaar let str = strpart(str, 0, i) . middle . strpart(str, i + 2) 143071d4279SBram Moolenaar let i = stridx(str, '%') 144071d4279SBram Moolenaar endwhile 145071d4279SBram Moolenaar return str 146071d4279SBram Moolenaar endfunction 147071d4279SBram Moolenaar 148071d4279SBram Moolenaar function! s:position_cursor() 149071d4279SBram Moolenaar if search('{cursor}') > 0 150071d4279SBram Moolenaar let pos = line('.') 151071d4279SBram Moolenaar let line = getline(pos) 152071d4279SBram Moolenaar let cursor = stridx(line, '{cursor}') 153071d4279SBram Moolenaar call setline(pos, substitute(line, '{cursor}', '', '')) 154071d4279SBram Moolenaar endif 155071d4279SBram Moolenaar startinsert! 156071d4279SBram Moolenaar endfunction 157071d4279SBram Moolenaar 158071d4279SBram Moolenaar " Internal function to create a new entry in the ChangeLog 159071d4279SBram Moolenaar function! s:new_changelog_entry() 160071d4279SBram Moolenaar " Deal with 'paste' option 161071d4279SBram Moolenaar let save_paste = &paste 162071d4279SBram Moolenaar let &paste = 1 163071d4279SBram Moolenaar 1 164071d4279SBram Moolenaar " Look for an entry for today by our user 165071d4279SBram Moolenaar let date = strftime(g:changelog_timeformat) 166071d4279SBram Moolenaar let search = s:substitute_items(g:changelog_date_entry_search, date, 167071d4279SBram Moolenaar \g:changelog_username) 168071d4279SBram Moolenaar if search(search) > 0 169071d4279SBram Moolenaar " Ok, now we look for the end of the date-entry, and add an entry 170071d4279SBram Moolenaar let pos = nextnonblank(line('.') + 1) 171071d4279SBram Moolenaar let line = getline(pos) 172071d4279SBram Moolenaar while line =~ '^\s\+\S\+' 173071d4279SBram Moolenaar let pos = pos + 1 174071d4279SBram Moolenaar let line = getline(pos) 175071d4279SBram Moolenaar endwhile 176071d4279SBram Moolenaar let insert = s:substitute_items(g:changelog_new_entry_format, 177071d4279SBram Moolenaar \'', '') 178071d4279SBram Moolenaar execute "normal! ".(pos - 1)."Go".insert 179071d4279SBram Moolenaar execute pos 180071d4279SBram Moolenaar else 181071d4279SBram Moolenaar " Flag for removing empty lines at end of new ChangeLogs 182071d4279SBram Moolenaar let remove_empty = line('$') == 1 183071d4279SBram Moolenaar 184071d4279SBram Moolenaar " No entry today, so create a date-user header and insert an entry 185071d4279SBram Moolenaar let todays_entry = s:substitute_items(g:changelog_new_date_format, 186071d4279SBram Moolenaar \date, g:changelog_username) 187071d4279SBram Moolenaar " Make sure we have a cursor positioning 188071d4279SBram Moolenaar if stridx(todays_entry, '{cursor}') == -1 189071d4279SBram Moolenaar let todays_entry = todays_entry.'{cursor}' 190071d4279SBram Moolenaar endif 191071d4279SBram Moolenaar 192071d4279SBram Moolenaar " Now do the work 193071d4279SBram Moolenaar execute "normal! i".todays_entry 194071d4279SBram Moolenaar if remove_empty 195071d4279SBram Moolenaar while getline('$') == '' 196071d4279SBram Moolenaar $delete 197071d4279SBram Moolenaar endwhile 198071d4279SBram Moolenaar endif 199071d4279SBram Moolenaar 200071d4279SBram Moolenaar 1 201071d4279SBram Moolenaar endif 202071d4279SBram Moolenaar 203071d4279SBram Moolenaar call s:position_cursor() 204071d4279SBram Moolenaar 205071d4279SBram Moolenaar " And reset 'paste' option 206071d4279SBram Moolenaar let &paste = save_paste 207071d4279SBram Moolenaar endfunction 208071d4279SBram Moolenaar 209071d4279SBram Moolenaar if exists(":NewChangelogEntry") != 2 210071d4279SBram Moolenaar map <buffer> <silent> <Leader>o <Esc>:call <SID>new_changelog_entry()<CR> 211071d4279SBram Moolenaar command! -nargs=0 NewChangelogEntry call s:new_changelog_entry() 212071d4279SBram Moolenaar endif 213071d4279SBram Moolenaar 214*42eeac35SBram Moolenaar let b:undo_ftplugin = "setl com< tw< fo< et< ai<" 215071d4279SBram Moolenaar 216071d4279SBram Moolenaar if &textwidth == 0 217071d4279SBram Moolenaar setlocal textwidth=78 218071d4279SBram Moolenaar endif 219071d4279SBram Moolenaar setlocal comments= 220071d4279SBram Moolenaar setlocal formatoptions+=t 221071d4279SBram Moolenaar setlocal noexpandtab 222*42eeac35SBram Moolenaar setlocal autoindent 223071d4279SBram Moolenaar 224*42eeac35SBram Moolenaar let &cpo = s:cpo_save 225*42eeac35SBram Moolenaar unlet s:cpo_save 226071d4279SBram Moolenaarelse 227071d4279SBram Moolenaar " Add the Changelog opening mapping 228071d4279SBram Moolenaar nmap <silent> <Leader>o :call <SID>open_changelog()<CR> 229071d4279SBram Moolenaar 230071d4279SBram Moolenaar function! s:open_changelog() 231071d4279SBram Moolenaar if filereadable('ChangeLog') 232071d4279SBram Moolenaar if bufloaded('ChangeLog') 233071d4279SBram Moolenaar let buf = bufnr('ChangeLog') 234071d4279SBram Moolenaar execute "normal! \<C-W>t" 235071d4279SBram Moolenaar while winbufnr(winnr()) != buf 236071d4279SBram Moolenaar execute "normal! \<C-W>w" 237071d4279SBram Moolenaar endwhile 238071d4279SBram Moolenaar else 239071d4279SBram Moolenaar split ChangeLog 240071d4279SBram Moolenaar endif 241071d4279SBram Moolenaar 242071d4279SBram Moolenaar if exists("g:mapleader") 243071d4279SBram Moolenaar execute "normal " . g:mapleader . "o" 244071d4279SBram Moolenaar else 245071d4279SBram Moolenaar execute "normal \\o" 246071d4279SBram Moolenaar endif 247071d4279SBram Moolenaar startinsert! 248071d4279SBram Moolenaar endif 249071d4279SBram Moolenaar endfunction 250071d4279SBram Moolenaarendif 251