blob: e9ec4d4282bcec8883c81dcc605c6456f071044f [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001" Vim filetype plugin file
Bram Moolenaar42eeac32005-06-29 22:40:58 +00002" Language: generic Changelog file
Bram Moolenaar57657d82006-04-21 22:12:41 +00003" Maintainer: Nikolai Weibull <now@bitwi.se>
Bram Moolenaar2c7a7632007-05-10 18:19:11 +00004" Latest Revision: 2007-05-06
Bram Moolenaar071d4272004-06-13 20:20:40 +00005" Variables:
Bram Moolenaar57657d82006-04-21 22:12:41 +00006" g:changelog_timeformat (deprecated: use g:changelog_dateformat instead) -
Bram Moolenaar42eeac32005-06-29 22:40:58 +00007" description: the timeformat used in ChangeLog entries.
8" default: "%Y-%m-%d".
Bram Moolenaar57657d82006-04-21 22:12:41 +00009" g:changelog_dateformat -
10" description: the format sent to strftime() to generate a date string.
11" default: "%Y-%m-%d".
Bram Moolenaar071d4272004-06-13 20:20:40 +000012" g:changelog_username -
Bram Moolenaar42eeac32005-06-29 22:40:58 +000013" description: the username to use in ChangeLog entries
14" default: try to deduce it from environment variables and system files.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015" Local Mappings:
16" <Leader>o -
Bram Moolenaar42eeac32005-06-29 22:40:58 +000017" adds a new changelog entry for the current user for the current date.
Bram Moolenaar071d4272004-06-13 20:20:40 +000018" Global Mappings:
19" <Leader>o -
Bram Moolenaar42eeac32005-06-29 22:40:58 +000020" switches to the ChangeLog buffer opened for the current directory, or
21" opens it in a new buffer if it exists in the current directory. Then
22" it does the same as the local <Leader>o described above.
Bram Moolenaar071d4272004-06-13 20:20:40 +000023" Notes:
24" run 'runtime ftplugin/changelog.vim' to enable the global mapping for
25" changelog files.
26" TODO:
27" should we perhaps open the ChangeLog file even if it doesn't exist already?
28" Problem is that you might end up with ChangeLog files all over the place.
29
30" If 'filetype' isn't "changelog", we must have been to add ChangeLog opener
Bram Moolenaar57657d82006-04-21 22:12:41 +000031if &filetype == 'changelog'
32 if exists('b:did_ftplugin')
Bram Moolenaar071d4272004-06-13 20:20:40 +000033 finish
34 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000035 let b:did_ftplugin = 1
36
Bram Moolenaar42eeac32005-06-29 22:40:58 +000037 let s:cpo_save = &cpo
38 set cpo&vim
Bram Moolenaar071d4272004-06-13 20:20:40 +000039
Bram Moolenaar57657d82006-04-21 22:12:41 +000040 " Set up the format used for dates.
41 if !exists('g:changelog_dateformat')
42 if exists('g:changelog_timeformat')
43 let g:changelog_dateformat = g:changelog_timeformat
44 else
45 let g:changelog_dateformat = "%Y-%m-%d"
46 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000047 endif
48
49 " Try to figure out a reasonable username of the form:
Bram Moolenaar57657d82006-04-21 22:12:41 +000050 " Full Name <user@host>.
51 if !exists('g:changelog_username')
52 if exists('$EMAIL') && $EMAIL != ''
Bram Moolenaar071d4272004-06-13 20:20:40 +000053 let g:changelog_username = $EMAIL
Bram Moolenaar57657d82006-04-21 22:12:41 +000054 elseif exists('$EMAIL_ADDRESS') && $EMAIL_ADDRESS != ''
55 " This is some Debian junk if I remember correctly.
56 let g:changelog_username = $EMAIL_ADDRESS
Bram Moolenaar071d4272004-06-13 20:20:40 +000057 else
Bram Moolenaar57657d82006-04-21 22:12:41 +000058 " Get the users login name.
Bram Moolenaar071d4272004-06-13 20:20:40 +000059 let login = system('whoami')
60 if v:shell_error
Bram Moolenaar42eeac32005-06-29 22:40:58 +000061 let login = 'unknown'
Bram Moolenaar071d4272004-06-13 20:20:40 +000062 else
Bram Moolenaar42eeac32005-06-29 22:40:58 +000063 let newline = stridx(login, "\n")
64 if newline != -1
65 let login = strpart(login, 0, newline)
66 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000067 endif
68
Bram Moolenaar57657d82006-04-21 22:12:41 +000069 " Try to get the full name from gecos field in /etc/passwd.
Bram Moolenaar071d4272004-06-13 20:20:40 +000070 if filereadable('/etc/passwd')
Bram Moolenaar57657d82006-04-21 22:12:41 +000071 for line in readfile('/etc/passwd')
72 if line =~ '^' . login
73 let name = substitute(line,'^\%([^:]*:\)\{4}\([^:]*\):.*$','\1','')
74 " Only keep stuff before the first comma.
75 let comma = stridx(name, ',')
76 if comma != -1
77 let name = strpart(name, 0, comma)
78 endif
79 " And substitute & in the real name with the login of our user.
80 let amp = stridx(name, '&')
81 if amp != -1
82 let name = strpart(name, 0, amp) . toupper(login[0]) .
83 \ strpart(login, 1) . strpart(name, amp + 1)
84 endif
85 endif
86 endfor
Bram Moolenaar071d4272004-06-13 20:20:40 +000087 endif
88
Bram Moolenaar57657d82006-04-21 22:12:41 +000089 " If we haven't found a name, try to gather it from other places.
90 if !exists('name')
91 " Maybe the environment has something of interest.
Bram Moolenaar42eeac32005-06-29 22:40:58 +000092 if exists("$NAME")
93 let name = $NAME
94 else
95 " No? well, use the login name and capitalize first
Bram Moolenaar57657d82006-04-21 22:12:41 +000096 " character.
Bram Moolenaar42eeac32005-06-29 22:40:58 +000097 let name = toupper(login[0]) . strpart(login, 1)
98 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000099 endif
100
Bram Moolenaar57657d82006-04-21 22:12:41 +0000101 " Get our hostname.
102 let hostname = system('hostname')
Bram Moolenaar071d4272004-06-13 20:20:40 +0000103 if v:shell_error
Bram Moolenaar57657d82006-04-21 22:12:41 +0000104 let hostname = 'localhost'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000105 else
Bram Moolenaar42eeac32005-06-29 22:40:58 +0000106 let newline = stridx(hostname, "\n")
107 if newline != -1
108 let hostname = strpart(hostname, 0, newline)
109 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000110 endif
111
Bram Moolenaar57657d82006-04-21 22:12:41 +0000112 " And finally set the username.
113 let g:changelog_username = name . ' <' . login . '@' . hostname . '>'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000114 endif
115 endif
116
Bram Moolenaar57657d82006-04-21 22:12:41 +0000117 " Format used for new date entries.
118 if !exists('g:changelog_new_date_format')
Bram Moolenaar071d4272004-06-13 20:20:40 +0000119 let g:changelog_new_date_format = "%d %u\n\n\t* %c\n\n"
120 endif
121
Bram Moolenaar57657d82006-04-21 22:12:41 +0000122 " Format used for new entries to current date entry.
123 if !exists('g:changelog_new_entry_format')
Bram Moolenaar071d4272004-06-13 20:20:40 +0000124 let g:changelog_new_entry_format = "\t* %c"
125 endif
126
Bram Moolenaar57657d82006-04-21 22:12:41 +0000127 " Regular expression used to find a given date entry.
128 if !exists('g:changelog_date_entry_search')
Bram Moolenaar071d4272004-06-13 20:20:40 +0000129 let g:changelog_date_entry_search = '^\s*%d\_s*%u'
130 endif
131
Bram Moolenaar2c7a7632007-05-10 18:19:11 +0000132 " Regular expression used to find the end of a date entry
133 if !exists('g:changelog_date_end_entry_search')
134 let g:changelog_date_entry_search = '^\s*$'
135 endif
136
137
Bram Moolenaar57657d82006-04-21 22:12:41 +0000138 " Substitutes specific items in new date-entry formats and search strings.
139 " Can be done with substitute of course, but unclean, and need \@! then.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000140 function! s:substitute_items(str, date, user)
141 let str = a:str
Bram Moolenaar57657d82006-04-21 22:12:41 +0000142 let middles = {'%': '%', 'd': a:date, 'u': a:user, 'c': '{cursor}'}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000143 let i = stridx(str, '%')
144 while i != -1
Bram Moolenaar57657d82006-04-21 22:12:41 +0000145 let inc = 0
146 if has_key(middles, str[i + 1])
147 let mid = middles[str[i + 1]]
148 let str = strpart(str, 0, i) . mid . strpart(str, i + 2)
149 let inc = strlen(mid)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000150 endif
Bram Moolenaar57657d82006-04-21 22:12:41 +0000151 let i = stridx(str, '%', i + 1 + inc)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000152 endwhile
153 return str
154 endfunction
155
Bram Moolenaar57657d82006-04-21 22:12:41 +0000156 " Position the cursor once we've done all the funky substitution.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000157 function! s:position_cursor()
158 if search('{cursor}') > 0
Bram Moolenaar57657d82006-04-21 22:12:41 +0000159 let lnum = line('.')
160 let line = getline(lnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000161 let cursor = stridx(line, '{cursor}')
Bram Moolenaar57657d82006-04-21 22:12:41 +0000162 call setline(lnum, substitute(line, '{cursor}', '', ''))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000163 endif
164 startinsert!
165 endfunction
166
Bram Moolenaar57657d82006-04-21 22:12:41 +0000167 " Internal function to create a new entry in the ChangeLog.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000168 function! s:new_changelog_entry()
Bram Moolenaar57657d82006-04-21 22:12:41 +0000169 " Deal with 'paste' option.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000170 let save_paste = &paste
171 let &paste = 1
Bram Moolenaar57657d82006-04-21 22:12:41 +0000172 call cursor(1, 1)
173 " Look for an entry for today by our user.
174 let date = strftime(g:changelog_dateformat)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000175 let search = s:substitute_items(g:changelog_date_entry_search, date,
Bram Moolenaar57657d82006-04-21 22:12:41 +0000176 \ g:changelog_username)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000177 if search(search) > 0
Bram Moolenaar57657d82006-04-21 22:12:41 +0000178 " Ok, now we look for the end of the date entry, and add an entry.
179 call cursor(nextnonblank(line('.') + 1), 1)
Bram Moolenaar2c7a7632007-05-10 18:19:11 +0000180 if search(g:changelog_date_end_entry_search, 'W') > 0
Bram Moolenaar57657d82006-04-21 22:12:41 +0000181 let p = line('.') - 1
182 else
183 let p = line('.')
184 endif
185 let ls = split(s:substitute_items(g:changelog_new_entry_format, '', ''),
186 \ '\n')
187 call append(p, ls)
188 call cursor(p + 1, 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000189 else
Bram Moolenaar57657d82006-04-21 22:12:41 +0000190 " Flag for removing empty lines at end of new ChangeLogs.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000191 let remove_empty = line('$') == 1
192
Bram Moolenaar57657d82006-04-21 22:12:41 +0000193 " No entry today, so create a date-user header and insert an entry.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000194 let todays_entry = s:substitute_items(g:changelog_new_date_format,
Bram Moolenaar57657d82006-04-21 22:12:41 +0000195 \ date, g:changelog_username)
196 " Make sure we have a cursor positioning.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000197 if stridx(todays_entry, '{cursor}') == -1
Bram Moolenaar57657d82006-04-21 22:12:41 +0000198 let todays_entry = todays_entry . '{cursor}'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000199 endif
200
Bram Moolenaar57657d82006-04-21 22:12:41 +0000201 " Now do the work.
202 call append(0, split(todays_entry, '\n'))
203
204 " Remove empty lines at end of file.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000205 if remove_empty
Bram Moolenaar57657d82006-04-21 22:12:41 +0000206 $-/^\s*$/-1,$delete
Bram Moolenaar071d4272004-06-13 20:20:40 +0000207 endif
208
Bram Moolenaar57657d82006-04-21 22:12:41 +0000209 " Reposition cursor once we're done.
210 call cursor(1, 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000211 endif
212
213 call s:position_cursor()
214
215 " And reset 'paste' option
216 let &paste = save_paste
217 endfunction
218
219 if exists(":NewChangelogEntry") != 2
220 map <buffer> <silent> <Leader>o <Esc>:call <SID>new_changelog_entry()<CR>
221 command! -nargs=0 NewChangelogEntry call s:new_changelog_entry()
222 endif
223
Bram Moolenaar57657d82006-04-21 22:12:41 +0000224 let b:undo_ftplugin = "setl com< fo< et< ai<"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000225
Bram Moolenaar071d4272004-06-13 20:20:40 +0000226 setlocal comments=
227 setlocal formatoptions+=t
228 setlocal noexpandtab
Bram Moolenaar42eeac32005-06-29 22:40:58 +0000229 setlocal autoindent
Bram Moolenaar071d4272004-06-13 20:20:40 +0000230
Bram Moolenaar57657d82006-04-21 22:12:41 +0000231 if &textwidth == 0
232 setlocal textwidth=78
233 let b:undo_ftplugin .= " tw<"
234 endif
235
Bram Moolenaar42eeac32005-06-29 22:40:58 +0000236 let &cpo = s:cpo_save
237 unlet s:cpo_save
Bram Moolenaar071d4272004-06-13 20:20:40 +0000238else
239 " Add the Changelog opening mapping
240 nmap <silent> <Leader>o :call <SID>open_changelog()<CR>
241
242 function! s:open_changelog()
Bram Moolenaar57657d82006-04-21 22:12:41 +0000243 if !filereadable('ChangeLog')
244 return
Bram Moolenaar071d4272004-06-13 20:20:40 +0000245 endif
Bram Moolenaar57657d82006-04-21 22:12:41 +0000246 let buf = bufnr('ChangeLog')
247 if buf != -1
248 if bufwinnr(buf) != -1
Bram Moolenaar2c7a7632007-05-10 18:19:11 +0000249 execute bufwinnr(buf) . 'wincmd w'
Bram Moolenaar57657d82006-04-21 22:12:41 +0000250 else
Bram Moolenaar2c7a7632007-05-10 18:19:11 +0000251 execute 'sbuffer' buf
Bram Moolenaar57657d82006-04-21 22:12:41 +0000252 endif
253 else
254 split ChangeLog
255 endif
256
257 call s:new_changelog_entry()
Bram Moolenaar071d4272004-06-13 20:20:40 +0000258 endfunction
259endif