Added optional extra caption levels to diary index.

Added the option 'diary_caption_level', which controls the presence of
captions in the diary index linking to headers within the diary pages.

Possible values:
-1:  No headers are read from the diary page.
 0:  The first header from the diary page is used as the caption.
       There are no sub-captions.
 1:  Captions are created for headers of level 1 in the diary page.
 2:  Captions are created for headers up to level 2 in the diary page.
 etc.

When the value is >= 1, the primary caption of each diary page is set to
the first header read from that page if it is the unique lowest-level
header.
This commit is contained in:
Eric Langlois 2019-03-19 22:59:24 -04:00 committed by Henry Qin
parent 7d82c7541d
commit 8f5d38365b
3 changed files with 131 additions and 21 deletions

View File

@ -63,26 +63,98 @@ function! s:get_month_name(month)
return vimwiki#vars#get_global('diary_months')[str2nr(a:month)]
endfunction
function! s:get_first_header(fl)
" Get the first header in the file within the first s:vimwiki_max_scan_for_caption lines.
let header_rx = vimwiki#vars#get_syntaxlocal('rxHeader')
for line in readfile(a:fl, '', s:vimwiki_max_scan_for_caption)
if line =~# header_rx
return vimwiki#u#trim(matchstr(line, header_rx))
endif
endfor
return ''
endfunction
function! s:get_all_headers(fl, maxlevel)
" Get a list of all headers in a file up to a given level.
" Returns a list whose elements are pairs [level, title]
let headers_rx = {}
for i in range(1, a:maxlevel)
let headers_rx[i] = vimwiki#vars#get_syntaxlocal('rxH'.i.'_Text')
endfor
let headers = []
for line in readfile(a:fl, '')
for [i, header_rx] in items(headers_rx)
if line =~# header_rx
call add(headers, [i, vimwiki#u#trim(matchstr(line, header_rx))])
break
endif
endfor
endfor
return headers
endfunction
function! s:count_headers_level_less_equal(headers, maxlevel)
" Count headers with level <= maxlevel in a list of [level, title] pairs.
let l:count = 0
for [header_level, _] in a:headers
if header_level <= a:maxlevel
let l:count += 1
endif
endfor
return l:count
endfunction
function! s:get_min_header_level(headers)
" The minimum level of any header in a list of [level, title] pairs.
if len(a:headers) == 0
return 0
endif
let minlevel = a:headers[0][0]
for [level, _] in a:headers
let minlevel = min([minlevel, level])
endfor
return minlevel
endfunction
function! s:read_captions(files)
let result = {}
let rx_header = vimwiki#vars#get_syntaxlocal('rxHeader')
let caption_level = vimwiki#vars#get_wikilocal('diary_caption_level')
for fl in a:files
" remove paths and extensions
let fl_key = substitute(fnamemodify(fl, ':t'), vimwiki#vars#get_wikilocal('ext').'$', '', '')
let fl_captions = {}
if filereadable(fl)
for line in readfile(fl, '', s:vimwiki_max_scan_for_caption)
if line =~# rx_header && !has_key(result, fl_key)
let result[fl_key] = vimwiki#u#trim(matchstr(line, rx_header))
" Default; no captions from the file.
let fl_captions['top'] = ''
let fl_captions['rest'] = []
if caption_level >= 0 && filereadable(fl)
if caption_level == 0
" Take first header of any level as the top caption.
let fl_captions['top'] = s:get_first_header(fl)
else
let headers = s:get_all_headers(fl, caption_level)
if len(headers) > 0
" If first header is the only one at its level or less, then make it the top caption.
let [first_level, first_header] = headers[0]
if s:count_headers_level_less_equal(headers, first_level) == 1
let fl_captions['top'] = first_header
call remove(headers, 0)
endif
let min_header_level = s:get_min_header_level(headers)
for [level, header] in headers
call add(fl_captions['rest'], [level - min_header_level, header])
endfor
endif
endfor
endif
if !has_key(result, fl_key)
let result[fl_key] = ''
endif
endif
let fl_key = substitute(fnamemodify(fl, ':t'), vimwiki#vars#get_wikilocal('ext').'$', '', '')
let result[fl_key] = fl_captions
endfor
return result
endfunction
@ -149,22 +221,36 @@ function! s:format_diary()
call add(result, substitute(vimwiki#vars#get_syntaxlocal('rxH3_Template'),
\ '__Header__', s:get_month_name(month), ''))
for [fl, cap] in s:sort(items(g_files[year][month]))
for [fl, captions] in s:sort(items(g_files[year][month]))
let topcap = captions['top']
let link_tpl = vimwiki#vars#get_global('WikiLinkTemplate2')
if vimwiki#vars#get_wikilocal('syntax') == 'markdown'
let link_tpl = vimwiki#vars#get_syntaxlocal('Weblink1Template')
if empty(cap) " When using markdown syntax, we should ensure we always have a link description.
let cap = fl
if empty(topcap) " When using markdown syntax, we should ensure we always have a link description.
let topcap = fl
endif
elseif empty(cap)
let link_tpl = vimwiki#vars#get_global('WikiLinkTemplate1')
endif
let entry = substitute(link_tpl, '__LinkUrl__', fl, '')
let entry = substitute(entry, '__LinkDescription__', cap, '')
if empty(topcap)
let top_link_tpl = vimwiki#vars#get_global('WikiLinkTemplate1')
else
let top_link_tpl = link_tpl
endif
let entry = substitute(top_link_tpl, '__LinkUrl__', fl, '')
let entry = substitute(entry, '__LinkDescription__', topcap, '')
call add(result, repeat(' ', vimwiki#lst#get_list_margin()).'* '.entry)
for [depth, subcap] in captions['rest']
if empty(subcap)
continue
endif
let entry = substitute(link_tpl, '__LinkUrl__', fl.'#'.subcap, '')
let entry = substitute(entry, '__LinkDescription__', subcap, '')
call add(result, repeat(' ', vimwiki#lst#get_list_margin() * (2 + depth)).'- '.entry)
endfor
endfor
endfor
@ -285,7 +371,7 @@ function! vimwiki#diary#generate_diary_section()
let current_file = vimwiki#path#path_norm(expand("%:p"))
let diary_file = vimwiki#path#path_norm(s:diary_index())
if vimwiki#path#is_equal(current_file, diary_file)
let content_rx = '^\%(\s*\* \)\|\%(^\s*$\)\|\%('.vimwiki#vars#get_syntaxlocal('rxHeader').'\)'
let content_rx = '^\%(\s*[*-] \)\|\%(^\s*$\)\|\%('.vimwiki#vars#get_syntaxlocal('rxHeader').'\)'
call vimwiki#base#update_listing_in_buffer(s:format_diary(),
\ vimwiki#vars#get_wikilocal('diary_header'), content_rx, line('$')+1, 1, 1)
else
@ -324,4 +410,3 @@ function vimwiki#diary#calendar_sign(day, month, year)
\ a:year.'-'.month.'-'.day.vimwiki#vars#get_wikilocal('ext')
return filereadable(expand(sfile))
endfunction

View File

@ -254,6 +254,7 @@ function! s:populate_wikilocal_options()
\ 'diary_header': {'type': type(''), 'default': 'Diary', 'min_length': 1},
\ 'diary_index': {'type': type(''), 'default': 'diary', 'min_length': 1},
\ 'diary_rel_path': {'type': type(''), 'default': 'diary/', 'min_length': 1},
\ 'diary_caption_level': {'type': type(0), 'default': 0, 'min': -1, 'max': 6},
\ 'diary_sort': {'type': type(''), 'default': 'desc', 'possible_values': ['asc', 'desc']},
\ 'ext': {'type': type(''), 'default': '.wiki', 'min_length': 1},
\ 'index': {'type': type(''), 'default': 'index', 'min_length': 1},
@ -444,6 +445,9 @@ function! vimwiki#vars#populate_syntax_vars(syntax)
let g:vimwiki_syntax_variables[a:syntax]['rxH'.i] =
\ '^\s*'.header_symbol.'\{'.i.'}[^'.header_symbol.'].*[^'.header_symbol.']'
\ .header_symbol.'\{'.i.'}\s*$'
let g:vimwiki_syntax_variables[a:syntax]['rxH'.i.'_Text'] =
\ '^\s*'.header_symbol.'\{'.i.'}\zs[^'.header_symbol.'].*[^'.header_symbol.']\ze'
\ .header_symbol.'\{'.i.'}\s*$'
let g:vimwiki_syntax_variables[a:syntax]['rxH'.i.'_Start'] =
\ '^\s*'.header_symbol.'\{'.i.'}[^'.header_symbol.'].*[^'.header_symbol.']'
\ .header_symbol.'\{'.i.'}\s*$'
@ -460,6 +464,8 @@ function! vimwiki#vars#populate_syntax_vars(syntax)
\ repeat(header_symbol, i).' __Header__'
let g:vimwiki_syntax_variables[a:syntax]['rxH'.i] =
\ '^\s*'.header_symbol.'\{'.i.'}[^'.header_symbol.'].*$'
let g:vimwiki_syntax_variables[a:syntax]['rxH'.i.'_Text'] =
\ '^\s*'.header_symbol.'\{'.i.'}\zs[^'.header_symbol.'].*\ze$'
let g:vimwiki_syntax_variables[a:syntax]['rxH'.i.'_Start'] =
\ '^\s*'.header_symbol.'\{'.i.'}[^'.header_symbol.'].*$'
let g:vimwiki_syntax_variables[a:syntax]['rxH'.i.'_End'] =
@ -857,4 +863,3 @@ endfunction
function! vimwiki#vars#number_of_wikis()
return len(g:vimwiki_wikilocal_vars) - 1
endfunction

View File

@ -2244,6 +2244,26 @@ Description~
Sort links in a diary index page.
*vimwiki-option-diary_caption_level*
------------------------------------------------------------------------------
Key Default value~
diary_caption_level 0
Description~
Controls the presence of captions in the diary index linking to headers within
the diary pages.
Possible values:
-1: No headers are read from the diary page.
0: The first header from the diary page is used as the caption.
There are no sub-captions.
1: Captions are created for headers of level 1 in the diary page.
2: Captions are created for headers up to level 2 in the diary page.
etc.
When the value is >= 1, the primary caption of each diary page is set to the
first header read from that page if it is the unique lowest-level header.
*vimwiki-option-custom_wiki2html*
------------------------------------------------------------------------------
Key Default value~