Mercurial > vim
annotate runtime/ftplugin/changelog.vim @ 20843:1a9f8fe67cd7
Added tag v8.2.0973 for changeset bacc2ab118102345122ee9750ef10a76cab0996e
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 13 Jun 2020 19:15:04 +0200 |
parents | 17333ebd2bbd |
children | ebedba7a4898 |
rev | line source |
---|---|
7 | 1 " Vim filetype plugin file |
7272
17333ebd2bbd
commit https://github.com/vim/vim/commit/d042dc825c9b97dacd84d4728f88300da4d5b6b9
Christian Brabandt <cb@256bit.org>
parents:
5618
diff
changeset
|
2 " Language: generic Changelog file |
17333ebd2bbd
commit https://github.com/vim/vim/commit/d042dc825c9b97dacd84d4728f88300da4d5b6b9
Christian Brabandt <cb@256bit.org>
parents:
5618
diff
changeset
|
3 " Maintainer: Martin Florian <marfl@posteo.de> |
17333ebd2bbd
commit https://github.com/vim/vim/commit/d042dc825c9b97dacd84d4728f88300da4d5b6b9
Christian Brabandt <cb@256bit.org>
parents:
5618
diff
changeset
|
4 " Previous Maintainer: Nikolai Weibull <now@bitwi.se> |
17333ebd2bbd
commit https://github.com/vim/vim/commit/d042dc825c9b97dacd84d4728f88300da4d5b6b9
Christian Brabandt <cb@256bit.org>
parents:
5618
diff
changeset
|
5 " Latest Revision: 2015-10-25 |
7 | 6 " Variables: |
839 | 7 " g:changelog_timeformat (deprecated: use g:changelog_dateformat instead) - |
375 | 8 " description: the timeformat used in ChangeLog entries. |
9 " default: "%Y-%m-%d". | |
839 | 10 " g:changelog_dateformat - |
11 " description: the format sent to strftime() to generate a date string. | |
12 " default: "%Y-%m-%d". | |
7 | 13 " g:changelog_username - |
375 | 14 " description: the username to use in ChangeLog entries |
15 " default: try to deduce it from environment variables and system files. | |
7 | 16 " Local Mappings: |
17 " <Leader>o - | |
375 | 18 " adds a new changelog entry for the current user for the current date. |
7 | 19 " Global Mappings: |
20 " <Leader>o - | |
375 | 21 " switches to the ChangeLog buffer opened for the current directory, or |
22 " opens it in a new buffer if it exists in the current directory. Then | |
23 " it does the same as the local <Leader>o described above. | |
7 | 24 " Notes: |
25 " run 'runtime ftplugin/changelog.vim' to enable the global mapping for | |
26 " changelog files. | |
27 " TODO: | |
28 " should we perhaps open the ChangeLog file even if it doesn't exist already? | |
29 " Problem is that you might end up with ChangeLog files all over the place. | |
30 | |
31 " If 'filetype' isn't "changelog", we must have been to add ChangeLog opener | |
839 | 32 if &filetype == 'changelog' |
33 if exists('b:did_ftplugin') | |
7 | 34 finish |
35 endif | |
36 let b:did_ftplugin = 1 | |
37 | |
375 | 38 let s:cpo_save = &cpo |
39 set cpo&vim | |
7 | 40 |
839 | 41 " Set up the format used for dates. |
42 if !exists('g:changelog_dateformat') | |
43 if exists('g:changelog_timeformat') | |
44 let g:changelog_dateformat = g:changelog_timeformat | |
45 else | |
46 let g:changelog_dateformat = "%Y-%m-%d" | |
47 endif | |
7 | 48 endif |
49 | |
2034 | 50 function! s:username() |
51 if exists('g:changelog_username') | |
52 return g:changelog_username | |
53 elseif $EMAIL != "" | |
54 return $EMAIL | |
55 elseif $EMAIL_ADDRESS != "" | |
56 return $EMAIL_ADDRESS | |
57 endif | |
58 | |
59 let login = s:login() | |
60 return printf('%s <%s@%s>', s:name(login), login, s:hostname()) | |
61 endfunction | |
62 | |
63 function! s:login() | |
64 return s:trimmed_system_with_default('whoami', 'unknown') | |
65 endfunction | |
66 | |
67 function! s:trimmed_system_with_default(command, default) | |
68 return s:first_line(s:system_with_default(a:command, a:default)) | |
69 endfunction | |
70 | |
71 function! s:system_with_default(command, default) | |
72 let output = system(a:command) | |
73 if v:shell_error | |
74 return default | |
75 endif | |
76 return output | |
77 endfunction | |
78 | |
79 function! s:first_line(string) | |
80 return substitute(a:string, '\n.*$', "", "") | |
81 endfunction | |
7 | 82 |
2034 | 83 function! s:name(login) |
84 for name in [s:gecos_name(a:login), $NAME, s:capitalize(a:login)] | |
85 if name != "" | |
86 return name | |
7 | 87 endif |
2034 | 88 endfor |
89 endfunction | |
90 | |
91 function! s:gecos_name(login) | |
92 for line in s:try_reading_file('/etc/passwd') | |
93 if line =~ '^' . a:login . ':' | |
94 return substitute(s:passwd_field(line, 5), '&', s:capitalize(a:login), "") | |
95 endif | |
96 endfor | |
97 return "" | |
98 endfunction | |
7 | 99 |
2034 | 100 function! s:try_reading_file(path) |
101 try | |
102 return readfile(a:path) | |
2826 | 103 catch |
104 return [] | |
2034 | 105 endtry |
106 endfunction | |
7 | 107 |
2034 | 108 function! s:passwd_field(line, field) |
109 let fields = split(a:line, ':', 1) | |
3830 | 110 if len(fields) < a:field |
2034 | 111 return "" |
112 endif | |
3830 | 113 return fields[a:field - 1] |
2034 | 114 endfunction |
7 | 115 |
2034 | 116 function! s:capitalize(word) |
117 return toupper(a:word[0]) . strpart(a:word, 1) | |
118 endfunction | |
119 | |
120 function! s:hostname() | |
121 return s:trimmed_system_with_default('hostname', 'localhost') | |
122 endfunction | |
7 | 123 |
839 | 124 " Format used for new date entries. |
125 if !exists('g:changelog_new_date_format') | |
5568 | 126 let g:changelog_new_date_format = "%d %u\n\n\t* %p%c\n\n" |
7 | 127 endif |
128 | |
839 | 129 " Format used for new entries to current date entry. |
130 if !exists('g:changelog_new_entry_format') | |
5568 | 131 let g:changelog_new_entry_format = "\t* %p%c" |
7 | 132 endif |
133 | |
839 | 134 " Regular expression used to find a given date entry. |
135 if !exists('g:changelog_date_entry_search') | |
7 | 136 let g:changelog_date_entry_search = '^\s*%d\_s*%u' |
137 endif | |
138 | |
1213 | 139 " Regular expression used to find the end of a date entry |
140 if !exists('g:changelog_date_end_entry_search') | |
1621 | 141 let g:changelog_date_end_entry_search = '^\s*$' |
1213 | 142 endif |
143 | |
144 | |
839 | 145 " Substitutes specific items in new date-entry formats and search strings. |
146 " Can be done with substitute of course, but unclean, and need \@! then. | |
5568 | 147 function! s:substitute_items(str, date, user, prefix) |
7 | 148 let str = a:str |
5568 | 149 let middles = {'%': '%', 'd': a:date, 'u': a:user, 'p': a:prefix, 'c': '{cursor}'} |
7 | 150 let i = stridx(str, '%') |
151 while i != -1 | |
839 | 152 let inc = 0 |
153 if has_key(middles, str[i + 1]) | |
154 let mid = middles[str[i + 1]] | |
155 let str = strpart(str, 0, i) . mid . strpart(str, i + 2) | |
5618 | 156 let inc = strlen(mid) - 1 |
7 | 157 endif |
839 | 158 let i = stridx(str, '%', i + 1 + inc) |
7 | 159 endwhile |
160 return str | |
161 endfunction | |
162 | |
839 | 163 " Position the cursor once we've done all the funky substitution. |
7 | 164 function! s:position_cursor() |
165 if search('{cursor}') > 0 | |
839 | 166 let lnum = line('.') |
167 let line = getline(lnum) | |
7 | 168 let cursor = stridx(line, '{cursor}') |
839 | 169 call setline(lnum, substitute(line, '{cursor}', '', '')) |
7 | 170 endif |
7272
17333ebd2bbd
commit https://github.com/vim/vim/commit/d042dc825c9b97dacd84d4728f88300da4d5b6b9
Christian Brabandt <cb@256bit.org>
parents:
5618
diff
changeset
|
171 startinsert |
7 | 172 endfunction |
173 | |
839 | 174 " Internal function to create a new entry in the ChangeLog. |
5568 | 175 function! s:new_changelog_entry(prefix) |
839 | 176 " Deal with 'paste' option. |
7 | 177 let save_paste = &paste |
178 let &paste = 1 | |
839 | 179 call cursor(1, 1) |
180 " Look for an entry for today by our user. | |
181 let date = strftime(g:changelog_dateformat) | |
7 | 182 let search = s:substitute_items(g:changelog_date_entry_search, date, |
5568 | 183 \ s:username(), a:prefix) |
7 | 184 if search(search) > 0 |
839 | 185 " Ok, now we look for the end of the date entry, and add an entry. |
186 call cursor(nextnonblank(line('.') + 1), 1) | |
1213 | 187 if search(g:changelog_date_end_entry_search, 'W') > 0 |
2034 | 188 let p = (line('.') == line('$')) ? line('.') : line('.') - 1 |
839 | 189 else |
190 let p = line('.') | |
191 endif | |
5568 | 192 let ls = split(s:substitute_items(g:changelog_new_entry_format, '', '', a:prefix), |
839 | 193 \ '\n') |
194 call append(p, ls) | |
195 call cursor(p + 1, 1) | |
7 | 196 else |
839 | 197 " Flag for removing empty lines at end of new ChangeLogs. |
7 | 198 let remove_empty = line('$') == 1 |
199 | |
839 | 200 " No entry today, so create a date-user header and insert an entry. |
7 | 201 let todays_entry = s:substitute_items(g:changelog_new_date_format, |
5568 | 202 \ date, s:username(), a:prefix) |
839 | 203 " Make sure we have a cursor positioning. |
7 | 204 if stridx(todays_entry, '{cursor}') == -1 |
839 | 205 let todays_entry = todays_entry . '{cursor}' |
7 | 206 endif |
207 | |
839 | 208 " Now do the work. |
209 call append(0, split(todays_entry, '\n')) | |
5568 | 210 |
839 | 211 " Remove empty lines at end of file. |
7 | 212 if remove_empty |
839 | 213 $-/^\s*$/-1,$delete |
7 | 214 endif |
215 | |
839 | 216 " Reposition cursor once we're done. |
217 call cursor(1, 1) | |
7 | 218 endif |
219 | |
220 call s:position_cursor() | |
221 | |
222 " And reset 'paste' option | |
223 let &paste = save_paste | |
224 endfunction | |
225 | |
226 if exists(":NewChangelogEntry") != 2 | |
7272
17333ebd2bbd
commit https://github.com/vim/vim/commit/d042dc825c9b97dacd84d4728f88300da4d5b6b9
Christian Brabandt <cb@256bit.org>
parents:
5618
diff
changeset
|
227 nnoremap <buffer> <silent> <Leader>o :<C-u>call <SID>new_changelog_entry('')<CR> |
17333ebd2bbd
commit https://github.com/vim/vim/commit/d042dc825c9b97dacd84d4728f88300da4d5b6b9
Christian Brabandt <cb@256bit.org>
parents:
5618
diff
changeset
|
228 xnoremap <buffer> <silent> <Leader>o :<C-u>call <SID>new_changelog_entry('')<CR> |
5568 | 229 command! -nargs=0 NewChangelogEntry call s:new_changelog_entry('') |
7 | 230 endif |
231 | |
839 | 232 let b:undo_ftplugin = "setl com< fo< et< ai<" |
7 | 233 |
234 setlocal comments= | |
235 setlocal formatoptions+=t | |
236 setlocal noexpandtab | |
375 | 237 setlocal autoindent |
7 | 238 |
839 | 239 if &textwidth == 0 |
240 setlocal textwidth=78 | |
241 let b:undo_ftplugin .= " tw<" | |
242 endif | |
243 | |
375 | 244 let &cpo = s:cpo_save |
245 unlet s:cpo_save | |
7 | 246 else |
2034 | 247 let s:cpo_save = &cpo |
248 set cpo&vim | |
249 | |
7 | 250 " Add the Changelog opening mapping |
2034 | 251 nnoremap <silent> <Leader>o :call <SID>open_changelog()<CR> |
7 | 252 |
253 function! s:open_changelog() | |
2034 | 254 let path = expand('%:p:h') |
255 if exists('b:changelog_path') | |
256 let changelog = b:changelog_path | |
257 else | |
258 if exists('b:changelog_name') | |
259 let name = b:changelog_name | |
260 else | |
261 let name = 'ChangeLog' | |
262 endif | |
263 while isdirectory(path) | |
264 let changelog = path . '/' . name | |
265 if filereadable(changelog) | |
266 break | |
267 endif | |
268 let parent = substitute(path, '/\+[^/]*$', "", "") | |
269 if path == parent | |
270 break | |
271 endif | |
272 let path = parent | |
273 endwhile | |
274 endif | |
275 if !filereadable(changelog) | |
839 | 276 return |
277 endif | |
2034 | 278 |
279 if exists('b:changelog_entry_prefix') | |
280 let prefix = call(b:changelog_entry_prefix, []) | |
281 else | |
5568 | 282 let prefix = substitute(strpart(expand('%:p'), strlen(path)), '^/\+', "", "") |
2034 | 283 endif |
284 | |
285 let buf = bufnr(changelog) | |
839 | 286 if buf != -1 |
287 if bufwinnr(buf) != -1 | |
1213 | 288 execute bufwinnr(buf) . 'wincmd w' |
7 | 289 else |
1213 | 290 execute 'sbuffer' buf |
7 | 291 endif |
839 | 292 else |
2034 | 293 execute 'split' fnameescape(changelog) |
839 | 294 endif |
7 | 295 |
2034 | 296 call s:new_changelog_entry(prefix) |
7 | 297 endfunction |
2034 | 298 |
299 let &cpo = s:cpo_save | |
300 unlet s:cpo_save | |
7 | 301 endif |