blob: b4206a200906da135d96222c45358a608e396d2c [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>
4" Latest Revision: 2006-04-19
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 Moolenaar57657d82006-04-21 22:12:41 +0000132 " Substitutes specific items in new date-entry formats and search strings.
133 " Can be done with substitute of course, but unclean, and need \@! then.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000134 function! s:substitute_items(str, date, user)
135 let str = a:str
Bram Moolenaar57657d82006-04-21 22:12:41 +0000136 let middles = {'%': '%', 'd': a:date, 'u': a:user, 'c': '{cursor}'}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000137 let i = stridx(str, '%')
138 while i != -1
Bram Moolenaar57657d82006-04-21 22:12:41 +0000139 let inc = 0
140 if has_key(middles, str[i + 1])
141 let mid = middles[str[i + 1]]
142 let str = strpart(str, 0, i) . mid . strpart(str, i + 2)
143 let inc = strlen(mid)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000144 endif
Bram Moolenaar57657d82006-04-21 22:12:41 +0000145 let i = stridx(str, '%', i + 1 + inc)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000146 endwhile
147 return str
148 endfunction
149
Bram Moolenaar57657d82006-04-21 22:12:41 +0000150 " Position the cursor once we've done all the funky substitution.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000151 function! s:position_cursor()
152 if search('{cursor}') > 0
Bram Moolenaar57657d82006-04-21 22:12:41 +0000153 let lnum = line('.')
154 let line = getline(lnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000155 let cursor = stridx(line, '{cursor}')
Bram Moolenaar57657d82006-04-21 22:12:41 +0000156 call setline(lnum, substitute(line, '{cursor}', '', ''))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000157 endif
158 startinsert!
159 endfunction
160
Bram Moolenaar57657d82006-04-21 22:12:41 +0000161 " Internal function to create a new entry in the ChangeLog.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000162 function! s:new_changelog_entry()
Bram Moolenaar57657d82006-04-21 22:12:41 +0000163 " Deal with 'paste' option.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000164 let save_paste = &paste
165 let &paste = 1
Bram Moolenaar57657d82006-04-21 22:12:41 +0000166 call cursor(1, 1)
167 " Look for an entry for today by our user.
168 let date = strftime(g:changelog_dateformat)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000169 let search = s:substitute_items(g:changelog_date_entry_search, date,
Bram Moolenaar57657d82006-04-21 22:12:41 +0000170 \ g:changelog_username)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000171 if search(search) > 0
Bram Moolenaar57657d82006-04-21 22:12:41 +0000172 " Ok, now we look for the end of the date entry, and add an entry.
173 call cursor(nextnonblank(line('.') + 1), 1)
174 if search('^\s*$', 'W') > 0
175 let p = line('.') - 1
176 else
177 let p = line('.')
178 endif
179 let ls = split(s:substitute_items(g:changelog_new_entry_format, '', ''),
180 \ '\n')
181 call append(p, ls)
182 call cursor(p + 1, 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000183 else
Bram Moolenaar57657d82006-04-21 22:12:41 +0000184 " Flag for removing empty lines at end of new ChangeLogs.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000185 let remove_empty = line('$') == 1
186
Bram Moolenaar57657d82006-04-21 22:12:41 +0000187 " No entry today, so create a date-user header and insert an entry.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000188 let todays_entry = s:substitute_items(g:changelog_new_date_format,
Bram Moolenaar57657d82006-04-21 22:12:41 +0000189 \ date, g:changelog_username)
190 " Make sure we have a cursor positioning.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000191 if stridx(todays_entry, '{cursor}') == -1
Bram Moolenaar57657d82006-04-21 22:12:41 +0000192 let todays_entry = todays_entry . '{cursor}'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000193 endif
194
Bram Moolenaar57657d82006-04-21 22:12:41 +0000195 " Now do the work.
196 call append(0, split(todays_entry, '\n'))
197
198 " Remove empty lines at end of file.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000199 if remove_empty
Bram Moolenaar57657d82006-04-21 22:12:41 +0000200 $-/^\s*$/-1,$delete
Bram Moolenaar071d4272004-06-13 20:20:40 +0000201 endif
202
Bram Moolenaar57657d82006-04-21 22:12:41 +0000203 " Reposition cursor once we're done.
204 call cursor(1, 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000205 endif
206
207 call s:position_cursor()
208
209 " And reset 'paste' option
210 let &paste = save_paste
211 endfunction
212
213 if exists(":NewChangelogEntry") != 2
214 map <buffer> <silent> <Leader>o <Esc>:call <SID>new_changelog_entry()<CR>
215 command! -nargs=0 NewChangelogEntry call s:new_changelog_entry()
216 endif
217
Bram Moolenaar57657d82006-04-21 22:12:41 +0000218 let b:undo_ftplugin = "setl com< fo< et< ai<"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000219
Bram Moolenaar071d4272004-06-13 20:20:40 +0000220 setlocal comments=
221 setlocal formatoptions+=t
222 setlocal noexpandtab
Bram Moolenaar42eeac32005-06-29 22:40:58 +0000223 setlocal autoindent
Bram Moolenaar071d4272004-06-13 20:20:40 +0000224
Bram Moolenaar57657d82006-04-21 22:12:41 +0000225 if &textwidth == 0
226 setlocal textwidth=78
227 let b:undo_ftplugin .= " tw<"
228 endif
229
Bram Moolenaar42eeac32005-06-29 22:40:58 +0000230 let &cpo = s:cpo_save
231 unlet s:cpo_save
Bram Moolenaar071d4272004-06-13 20:20:40 +0000232else
233 " Add the Changelog opening mapping
234 nmap <silent> <Leader>o :call <SID>open_changelog()<CR>
235
236 function! s:open_changelog()
Bram Moolenaar57657d82006-04-21 22:12:41 +0000237 if !filereadable('ChangeLog')
238 return
Bram Moolenaar071d4272004-06-13 20:20:40 +0000239 endif
Bram Moolenaar57657d82006-04-21 22:12:41 +0000240 let buf = bufnr('ChangeLog')
241 if buf != -1
242 if bufwinnr(buf) != -1
243 execute buf . 'wincmd w'
244 else
245 execute 'bsplit' buf
246 endif
247 else
248 split ChangeLog
249 endif
250
251 call s:new_changelog_entry()
Bram Moolenaar071d4272004-06-13 20:20:40 +0000252 endfunction
253endif