1
0
Fork 0
mirror of https://github.com/vim/vim synced 2025-03-28 20:46:46 +01:00
vim/runtime/ftplugin/changelog.vim

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

314 lines
9.3 KiB
VimL
Raw Permalink Normal View History

2004-06-13 20:20:40 +00:00
" Vim filetype plugin file
2015-11-24 19:18:36 +01:00
" Language: generic Changelog file
" Maintainer: Martin Florian <marfl@posteo.de>
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
2021-10-23 12:08:41 +01:00
" Latest Revision: 2021-10-17
2004-06-13 20:20:40 +00:00
" Variables:
2006-04-21 22:12:41 +00:00
" g:changelog_timeformat (deprecated: use g:changelog_dateformat instead) -
2005-06-29 22:40:58 +00:00
" description: the timeformat used in ChangeLog entries.
" default: "%Y-%m-%d".
2006-04-21 22:12:41 +00:00
" g:changelog_dateformat -
" description: the format sent to strftime() to generate a date string.
" default: "%Y-%m-%d".
2004-06-13 20:20:40 +00:00
" g:changelog_username -
2005-06-29 22:40:58 +00:00
" description: the username to use in ChangeLog entries
" default: try to deduce it from environment variables and system files.
2004-06-13 20:20:40 +00:00
" Local Mappings:
" <Leader>o -
2005-06-29 22:40:58 +00:00
" adds a new changelog entry for the current user for the current date.
2004-06-13 20:20:40 +00:00
" Global Mappings:
" <Leader>o -
2005-06-29 22:40:58 +00:00
" switches to the ChangeLog buffer opened for the current directory, or
" opens it in a new buffer if it exists in the current directory. Then
" it does the same as the local <Leader>o described above.
2004-06-13 20:20:40 +00:00
" Notes:
" run 'runtime ftplugin/changelog.vim' to enable the global mapping for
" changelog files.
" TODO:
" should we perhaps open the ChangeLog file even if it doesn't exist already?
" Problem is that you might end up with ChangeLog files all over the place.
" If 'filetype' isn't "changelog", we must have been to add ChangeLog opener
2006-04-21 22:12:41 +00:00
if &filetype == 'changelog'
if exists('b:did_ftplugin')
2004-06-13 20:20:40 +00:00
finish
endif
let b:did_ftplugin = 1
2005-06-29 22:40:58 +00:00
let s:cpo_save = &cpo
set cpo&vim
2004-06-13 20:20:40 +00:00
2006-04-21 22:12:41 +00:00
" Set up the format used for dates.
if !exists('g:changelog_dateformat')
if exists('g:changelog_timeformat')
let g:changelog_dateformat = g:changelog_timeformat
else
let g:changelog_dateformat = "%Y-%m-%d"
endif
2004-06-13 20:20:40 +00:00
endif
2010-01-06 20:54:52 +01:00
function! s:username()
if exists('g:changelog_username')
return g:changelog_username
elseif $EMAIL != ""
return $EMAIL
elseif $EMAIL_ADDRESS != ""
return $EMAIL_ADDRESS
endif
let s:default_login = 'unknown'
2021-10-23 12:08:41 +01:00
" Disabled by default for security reasons.
if dist#vim#IsSafeExecutable('changelog', 'whoami')
let login = s:login()
else
let login = s:default_login
endif
2010-01-06 20:54:52 +01:00
return printf('%s <%s@%s>', s:name(login), login, s:hostname())
endfunction
2004-06-13 20:20:40 +00:00
2010-01-06 20:54:52 +01:00
function! s:login()
return s:trimmed_system_with_default('whoami', s:default_login)
2010-01-06 20:54:52 +01:00
endfunction
2004-06-13 20:20:40 +00:00
2010-01-06 20:54:52 +01:00
function! s:trimmed_system_with_default(command, default)
return s:first_line(s:system_with_default(a:command, a:default))
endfunction
function! s:system_with_default(command, default)
let output = system(a:command)
if v:shell_error
return a:default
2010-01-06 20:54:52 +01:00
endif
return output
endfunction
function! s:first_line(string)
return substitute(a:string, '\n.*$', "", "")
endfunction
function! s:name(login)
for name in [s:gecos_name(a:login), $NAME, s:capitalize(a:login)]
if name != ""
return name
2004-06-13 20:20:40 +00:00
endif
2010-01-06 20:54:52 +01:00
endfor
endfunction
2004-06-13 20:20:40 +00:00
2010-01-06 20:54:52 +01:00
function! s:gecos_name(login)
for line in s:try_reading_file('/etc/passwd')
if line =~ '^' . a:login . ':'
return substitute(s:passwd_field(line, 5), '&', s:capitalize(a:login), "")
2004-06-13 20:20:40 +00:00
endif
2010-01-06 20:54:52 +01:00
endfor
return ""
endfunction
2004-06-13 20:20:40 +00:00
2010-01-06 20:54:52 +01:00
function! s:try_reading_file(path)
try
return readfile(a:path)
2011-05-10 17:18:44 +02:00
catch
return []
2010-01-06 20:54:52 +01:00
endtry
endfunction
function! s:passwd_field(line, field)
let fields = split(a:line, ':', 1)
2012-09-21 14:54:30 +02:00
if len(fields) < a:field
2010-01-06 20:54:52 +01:00
return ""
2004-06-13 20:20:40 +00:00
endif
2012-09-21 14:54:30 +02:00
return fields[a:field - 1]
2010-01-06 20:54:52 +01:00
endfunction
function! s:capitalize(word)
return toupper(a:word[0]) . strpart(a:word, 1)
endfunction
function! s:hostname()
return s:trimmed_system_with_default('hostname', 'localhost')
endfunction
2004-06-13 20:20:40 +00:00
2006-04-21 22:12:41 +00:00
" Format used for new date entries.
if !exists('g:changelog_new_date_format')
2013-12-15 10:02:33 +01:00
let g:changelog_new_date_format = "%d %u\n\n\t* %p%c\n\n"
2004-06-13 20:20:40 +00:00
endif
2006-04-21 22:12:41 +00:00
" Format used for new entries to current date entry.
if !exists('g:changelog_new_entry_format')
2013-12-15 10:02:33 +01:00
let g:changelog_new_entry_format = "\t* %p%c"
2004-06-13 20:20:40 +00:00
endif
2006-04-21 22:12:41 +00:00
" Regular expression used to find a given date entry.
if !exists('g:changelog_date_entry_search')
2004-06-13 20:20:40 +00:00
let g:changelog_date_entry_search = '^\s*%d\_s*%u'
endif
2007-05-10 18:19:11 +00:00
" Regular expression used to find the end of a date entry
if !exists('g:changelog_date_end_entry_search')
2008-06-24 21:56:24 +00:00
let g:changelog_date_end_entry_search = '^\s*$'
2007-05-10 18:19:11 +00:00
endif
2006-04-21 22:12:41 +00:00
" Substitutes specific items in new date-entry formats and search strings.
" Can be done with substitute of course, but unclean, and need \@! then.
2013-12-15 10:02:33 +01:00
function! s:substitute_items(str, date, user, prefix)
2004-06-13 20:20:40 +00:00
let str = a:str
2013-12-15 10:02:33 +01:00
let middles = {'%': '%', 'd': a:date, 'u': a:user, 'p': a:prefix, 'c': '{cursor}'}
2004-06-13 20:20:40 +00:00
let i = stridx(str, '%')
while i != -1
2006-04-21 22:12:41 +00:00
let inc = 0
if has_key(middles, str[i + 1])
let mid = middles[str[i + 1]]
let str = strpart(str, 0, i) . mid . strpart(str, i + 2)
2014-01-23 14:24:41 +01:00
let inc = strlen(mid) - 1
2004-06-13 20:20:40 +00:00
endif
2006-04-21 22:12:41 +00:00
let i = stridx(str, '%', i + 1 + inc)
2004-06-13 20:20:40 +00:00
endwhile
return str
endfunction
2006-04-21 22:12:41 +00:00
" Position the cursor once we've done all the funky substitution.
2004-06-13 20:20:40 +00:00
function! s:position_cursor()
if search('{cursor}') > 0
2006-04-21 22:12:41 +00:00
let lnum = line('.')
let line = getline(lnum)
2004-06-13 20:20:40 +00:00
let cursor = stridx(line, '{cursor}')
2006-04-21 22:12:41 +00:00
call setline(lnum, substitute(line, '{cursor}', '', ''))
2004-06-13 20:20:40 +00:00
endif
2015-11-24 19:18:36 +01:00
startinsert
2004-06-13 20:20:40 +00:00
endfunction
2006-04-21 22:12:41 +00:00
" Internal function to create a new entry in the ChangeLog.
2013-12-15 10:02:33 +01:00
function! s:new_changelog_entry(prefix)
2006-04-21 22:12:41 +00:00
" Deal with 'paste' option.
2004-06-13 20:20:40 +00:00
let save_paste = &paste
let &paste = 1
2006-04-21 22:12:41 +00:00
call cursor(1, 1)
" Look for an entry for today by our user.
let date = strftime(g:changelog_dateformat)
2004-06-13 20:20:40 +00:00
let search = s:substitute_items(g:changelog_date_entry_search, date,
2013-12-15 10:02:33 +01:00
\ s:username(), a:prefix)
2004-06-13 20:20:40 +00:00
if search(search) > 0
2006-04-21 22:12:41 +00:00
" Ok, now we look for the end of the date entry, and add an entry.
call cursor(nextnonblank(line('.') + 1), 1)
2007-05-10 18:19:11 +00:00
if search(g:changelog_date_end_entry_search, 'W') > 0
2010-01-06 20:54:52 +01:00
let p = (line('.') == line('$')) ? line('.') : line('.') - 1
2006-04-21 22:12:41 +00:00
else
let p = line('.')
endif
2013-12-15 10:02:33 +01:00
let ls = split(s:substitute_items(g:changelog_new_entry_format, '', '', a:prefix),
2006-04-21 22:12:41 +00:00
\ '\n')
call append(p, ls)
call cursor(p + 1, 1)
2004-06-13 20:20:40 +00:00
else
2006-04-21 22:12:41 +00:00
" Flag for removing empty lines at end of new ChangeLogs.
2004-06-13 20:20:40 +00:00
let remove_empty = line('$') == 1
2006-04-21 22:12:41 +00:00
" No entry today, so create a date-user header and insert an entry.
2004-06-13 20:20:40 +00:00
let todays_entry = s:substitute_items(g:changelog_new_date_format,
2013-12-15 10:02:33 +01:00
\ date, s:username(), a:prefix)
2006-04-21 22:12:41 +00:00
" Make sure we have a cursor positioning.
2004-06-13 20:20:40 +00:00
if stridx(todays_entry, '{cursor}') == -1
2006-04-21 22:12:41 +00:00
let todays_entry = todays_entry . '{cursor}'
2004-06-13 20:20:40 +00:00
endif
2006-04-21 22:12:41 +00:00
" Now do the work.
call append(0, split(todays_entry, '\n'))
2013-12-15 10:02:33 +01:00
2006-04-21 22:12:41 +00:00
" Remove empty lines at end of file.
2004-06-13 20:20:40 +00:00
if remove_empty
2006-04-21 22:12:41 +00:00
$-/^\s*$/-1,$delete
2004-06-13 20:20:40 +00:00
endif
2006-04-21 22:12:41 +00:00
" Reposition cursor once we're done.
call cursor(1, 1)
2004-06-13 20:20:40 +00:00
endif
call s:position_cursor()
" And reset 'paste' option
let &paste = save_paste
endfunction
2006-04-21 22:12:41 +00:00
let b:undo_ftplugin = "setl com< fo< et< ai<"
2004-06-13 20:20:40 +00:00
setlocal comments=
setlocal formatoptions+=t
setlocal noexpandtab
2005-06-29 22:40:58 +00:00
setlocal autoindent
2004-06-13 20:20:40 +00:00
2006-04-21 22:12:41 +00:00
if &textwidth == 0
setlocal textwidth=78
let b:undo_ftplugin .= " tw<"
endif
2021-10-23 12:08:41 +01:00
if !exists("no_plugin_maps") && !exists("no_changelog_maps") && exists(":NewChangelogEntry") != 2
nnoremap <buffer> <silent> <Leader>o :<C-u>call <SID>new_changelog_entry('')<CR>
xnoremap <buffer> <silent> <Leader>o :<C-u>call <SID>new_changelog_entry('')<CR>
command! -buffer -nargs=0 NewChangelogEntry call s:new_changelog_entry('')
let b:undo_ftplugin .= " | sil! exe 'nunmap <buffer> <Leader>o'" .
\ " | sil! exe 'vunmap <buffer> <Leader>o'" .
\ " | sil! delc NewChangelogEntry"
endif
2005-06-29 22:40:58 +00:00
let &cpo = s:cpo_save
unlet s:cpo_save
2004-06-13 20:20:40 +00:00
else
2010-01-06 20:54:52 +01:00
let s:cpo_save = &cpo
set cpo&vim
2021-10-23 12:08:41 +01:00
if !exists("no_plugin_maps") && !exists("no_changelog_maps")
" Add the Changelog opening mapping
nnoremap <silent> <Leader>o :call <SID>open_changelog()<CR>
let b:undo_ftplugin .= " | silent! exe 'nunmap <buffer> <Leader>o"
endif
2004-06-13 20:20:40 +00:00
function! s:open_changelog()
2010-01-06 20:54:52 +01:00
let path = expand('%:p:h')
if exists('b:changelog_path')
let changelog = b:changelog_path
else
if exists('b:changelog_name')
let name = b:changelog_name
else
let name = 'ChangeLog'
endif
while isdirectory(path)
let changelog = path . '/' . name
if filereadable(changelog)
break
endif
let parent = substitute(path, '/\+[^/]*$', "", "")
if path == parent
break
endif
let path = parent
endwhile
endif
if !filereadable(changelog)
2006-04-21 22:12:41 +00:00
return
endif
2010-01-06 20:54:52 +01:00
if exists('b:changelog_entry_prefix')
let prefix = call(b:changelog_entry_prefix, [])
else
2013-12-15 10:02:33 +01:00
let prefix = substitute(strpart(expand('%:p'), strlen(path)), '^/\+', "", "")
2010-01-06 20:54:52 +01:00
endif
let buf = bufnr(changelog)
2006-04-21 22:12:41 +00:00
if buf != -1
if bufwinnr(buf) != -1
2007-05-10 18:19:11 +00:00
execute bufwinnr(buf) . 'wincmd w'
2004-06-13 20:20:40 +00:00
else
2007-05-10 18:19:11 +00:00
execute 'sbuffer' buf
2004-06-13 20:20:40 +00:00
endif
2006-04-21 22:12:41 +00:00
else
2010-01-06 20:54:52 +01:00
execute 'split' fnameescape(changelog)
2004-06-13 20:20:40 +00:00
endif
2006-04-21 22:12:41 +00:00
2010-01-06 20:54:52 +01:00
call s:new_changelog_entry(prefix)
2004-06-13 20:20:40 +00:00
endfunction
2010-01-06 20:54:52 +01:00
let &cpo = s:cpo_save
unlet s:cpo_save
2004-06-13 20:20:40 +00:00
endif