vimwiki/autoload/vimwiki/lst.vim

1539 lines
44 KiB
VimL
Raw Normal View History

Version 1.0 * NEW: Issue 41: Table cell and column text objects. See `vimwiki-text-objects`. * NEW: Issue 42: Commands to move table columns left and right. See `:VimwikiTableMoveColumnLeft` and `:VimwikiTableMoveColumnRight`. * NEW: Issue 44: `<S-Tab>` should move cursor to the previous table cell. * NEW: Issue 45: It should be possible to indent tables. Indented tables are centered in html. * NEW: Issue 46: Do not htmlize some wiki pages (blacklist). New placeholder is added: `%nohtml`. See `vimwiki-nohtml`. * FIX: Issue 47: Lists aren't HTMLized properly. * FIX: Issue 48: With autochdir it is impossible to have path_html such as `d:\vimwiki\html\` * FIX: Issue 49: Table is not HTMLized properly at the end of wiki page. * FIX: Issue 50: Inline formatting is not performed in table cells. * FIX: Issue 51: Cannot insert '-' (minus) into table cells of the first column. * FIX: Issue 52: Table cell width is incorrect when double wide characters are used (ie. Chinese). Check `g:vimwiki_CJK_length`. * NEW: Issue 53: Wiki markup can not nested. (Use links and inline markup in Headers). * NEW: Issue 54: Highlight for placeholders. * NEW: Issue 56: Directory indexes. See `g:vimwiki_dir_link` option and `:VimwikiGenerateLinks` command. * NEW: Issue 58: Html new lines with `<br />`. Could be inserted with `<S-CR>` in insert mode. * FIX: Issue 59: List item's text can't be started from `*`. * NEW: Issue 60: Links inside completed gtd-items. * NEW: Issue 61: Headers numbering. See `g:vimwiki_html_header_numbering` and `g:vimwiki_html_header_numbering_sym` options. * FIX: Issue 63: Table cannot have leading empty cells in html. * FIX: Issue 65: Table separator is not htmlized right if on top of the table. * FIX: Issue 66: Table empty cells are very small in html. * FIX: Issue 67: Wrong html conversion of multilined list item with bold text on the start of next line. * FIX: Issue 68: auto-indent problem with langmap. * FIX: Issue 73: Link navigation by Tab. "Escaped" wiki-word should be skipped for navigation with `<tab>`. * FIX: Issue 75: `code` syntax doesn't display correctly in toc. * FIX: Issue 77: Diary index only showing link to today's diary entry file for extensions other than '.wiki'. * FIX: Issue 79: Further calendar.vim integration -- add sign to calendar date if it has corresponding diary page. * FIX: Issue 80: Debian Lenny GUI Vim 7.2 has problems with toggling inner todo list items. * FIX: Issue 81: Don't convert `WikiWord` as a link in html when `let g:vimwiki_camel_case = 0`
2010-05-12 02:00:00 +02:00
" vim:tabstop=2:shiftwidth=2:expandtab:foldmethod=marker:textwidth=79
" Vimwiki autoload plugin file
" Desc: Everything concerning lists and checkboxes
" Home: https://github.com/vimwiki/vimwiki/
if exists("g:loaded_vimwiki_list_auto") || &cp
finish
endif
let g:loaded_vimwiki_list_auto = 1
2014-01-06 13:30:33 +01:00
"incrementation functions for the various kinds of numbers {{{
function! s:increment_1(value) "{{{
return eval(a:value) + 1
endfunction "}}}
function! s:increment_A(value) "{{{
let list_of_chars = split(a:value, '.\zs')
let done = 0
for idx in reverse(range(len(list_of_chars)))
let cur_num = char2nr(list_of_chars[idx])
if cur_num < 90
let list_of_chars[idx] = nr2char(cur_num + 1)
let done = 1
break
else
let list_of_chars[idx] = 'A'
endif
endfor
if !done
call insert(list_of_chars, 'A')
endif
return join(list_of_chars, '')
endfunction "}}}
function! s:increment_a(value) "{{{
let list_of_chars = split(a:value, '.\zs')
let done = 0
for idx in reverse(range(len(list_of_chars)))
let cur_num = char2nr(list_of_chars[idx])
if cur_num < 122
let list_of_chars[idx] = nr2char(cur_num + 1)
let done = 1
break
else
let list_of_chars[idx] = 'a'
endif
endfor
if !done
call insert(list_of_chars, 'a')
endif
return join(list_of_chars, '')
endfunction "}}}
function! s:increment_I(value) "{{{
let subst_list = [ ['XLVIII$', 'IL'], ['VIII$', 'IX'], ['III$', 'IV'],
\ ['DCCCXCIX$', 'CM'], ['CCCXCIX$', 'CD'], ['LXXXIX$', 'XC'],
\ ['XXXIX$', 'XL'], ['\(I\{1,2\}\)$', '\1I'], ['CDXCIX$', 'D'],
\ ['CMXCIX$', 'M'], ['XCIX$', 'C'], ['I\([VXLCDM]\)$', '\1'],
\ ['\([VXLCDM]\)$', '\1I'] ]
for [regex, subst] in subst_list
if a:value =~# regex
return substitute(a:value, regex, subst, '')
endif
endfor
return ''
endfunction "}}}
function! s:increment_i(value) "{{{
let subst_list = [ ['xlviii$', 'il'], ['viii$', 'ix'], ['iii$', 'iv'],
\ ['dcccxcix$', 'cm'], ['cccxcix$', 'cd'], ['lxxxix$', 'xc'],
\ ['xxxix$', 'xl'], ['\(i\{1,2\}\)$', '\1i'], ['cdxcix$', 'd'],
\ ['cmxcix$', 'm'], ['xcix$', 'c'], ['i\([vxlcdm]\)$', '\1'],
\ ['\([vxlcdm]\)$', '\1i'] ]
for [regex, subst] in subst_list
if a:value =~# regex
return substitute(a:value, regex, subst, '')
endif
endfor
return ''
endfunction "}}}
2014-01-06 13:30:33 +01:00
"incrementation functions for the various kinds of numbers }}}
2014-01-06 13:30:33 +01:00
"utility functions {{{
function! s:substitute_rx_in_line(lnum, pattern, new_string) "{{{
call setline(a:lnum, substitute(getline(a:lnum), a:pattern, a:new_string,
\ ''))
endfunction "}}}
function! s:substitute_string_in_line(lnum, old_string, new_string) "{{{
call s:substitute_rx_in_line(a:lnum, vimwiki#u#escape(a:old_string),
\ a:new_string)
endfunction "}}}
function! s:first_char(string) "{{{
return matchstr(a:string, '^.')
endfunction "}}}
if exists("*strdisplaywidth") "{{{
function! s:string_length(str)
return strdisplaywidth(a:str)
endfunction
else
function! s:string_length(str)
return strlen(substitute(a:str, '.', 'x', 'g'))
endfunction
endif "}}}
2014-01-06 13:30:33 +01:00
function! vimwiki#lst#default_symbol() "{{{
return g:vimwiki_list_markers[0]
endfunction "}}}
function! vimwiki#lst#get_list_margin() "{{{
if VimwikiGet('list_margin') < 0
return &sw
else
return VimwikiGet('list_margin')
endif
endfunction "}}}
"Returns: the column where the text of a line starts (possible list item
"markers and checkboxes are skipped)
function! s:text_begin(lnum) "{{{
return s:string_length(matchstr(getline(a:lnum), g:vimwiki_rxListItem))
endfunction "}}}
"Returns: 2 if there is a marker and text
" 1 for a marker and no text
" 0 for no marker at all (empty line or only text)
function! s:line_has_marker(lnum) "{{{
if getline(a:lnum) =~# g:vimwiki_rxListItem.'\s*$'
return 1
elseif getline(a:lnum) =~# g:vimwiki_rxListItem.'\s*\S'
return 2
else
return 0
endif
endfunction "}}}
"utility functions }}}
2014-01-06 13:30:33 +01:00
"get properties of an item {{{
"Returns: the mainly used data structure in this file
"An item represents a single list item and is a dictionary with the keys
"lnum - the line number of the list item
"type - 1 for bulleted item, 2 for numbered item, 0 for a regular line
"mrkr - the concrete marker, e.g. '**' or 'b)'
"cb - the char in the checkbox or '' if there is no checkbox
function! s:get_item(lnum) "{{{
let item = {'lnum': a:lnum}
if a:lnum == 0 || a:lnum > line('$')
let item.type = 0
return item
endif
let matches = matchlist(getline(a:lnum), g:vimwiki_rxListItem)
if matches == [] ||
\ (matches[1] == '' && matches[2] == '') ||
\ (matches[1] != '' && matches[2] != '')
let item.type = 0
return item
endif
let item.cb = matches[3]
if matches[1] != ''
let item.type = 1
let item.mrkr = matches[1]
else
let item.type = 2
let item.mrkr = matches[2]
endif
return item
endfunction "}}}
function! s:empty_item() "{{{
return {'type': 0}
endfunction "}}}
"Returns: level of the line
"0 is the 'highest' level
function! s:get_level(lnum) "{{{
if getline(a:lnum) =~# '^\s*$'
return 0
endif
if VimwikiGet('syntax') !=? 'media'
let level = indent(a:lnum)
else
let level = s:string_length(matchstr(getline(a:lnum), s:rx_bullet_chars))-1
if level < 0
let level = (indent(a:lnum) == 0) ? 0 : 9999
endif
endif
return level
endfunction "}}}
2014-01-06 13:30:33 +01:00
"Returns: 1, a, i, A, I or ''
"If in doubt if alphanumeric character or romanian
"numeral, peek in the previous line
function! s:guess_kind_of_numbered_item(item) "{{{
if a:item.type != 2 | return '' | endif
let number_chars = a:item.mrkr[:-2]
let divisor = a:item.mrkr[-1:]
if number_chars =~# '\d\+'
2014-01-06 13:30:33 +01:00
return '1'
endif
if number_chars =~# '\l\+'
if number_chars !~# '^[ivxlcdm]\+' || index(s:number_kinds, 'i') == -1
return 'a'
else
let item_above = s:get_prev_list_item(a:item, 0)
if item_above.type != 0
if index(s:number_kinds, 'a') == -1 ||
\ (item_above.mrkr[-1:] !=# divisor && number_chars =~# 'i\+') ||
\ s:increment_i(item_above.mrkr[:-2]) ==# number_chars
return 'i'
else
return 'a'
endif
else
if number_chars =~# 'i\+' || index(s:number_kinds, 'a') == -1
return 'i'
else
return 'a'
endif
endif
endif
endif
if number_chars =~# '\u\+'
if number_chars !~# '^[IVXLCDM]\+' || index(s:number_kinds, 'I') == -1
return 'A'
else
let item_above = s:get_prev_list_item(a:item, 0)
if item_above.type != 0
if index(s:number_kinds, 'A') == -1 ||
\ (item_above.mrkr[-1:] !=# divisor && number_chars =~# 'I\+') ||
\ s:increment_I(item_above.mrkr[:-2]) ==# number_chars
return 'I'
else
return 'A'
endif
else
if number_chars =~# 'I\+' || index(s:number_kinds, 'A') == -1
return 'I'
else
return 'A'
endif
endif
endif
endif
endfunction "}}}
function! s:regexp_of_marker(item) "{{{
if a:item.type == 1
return vimwiki#u#escape(a:item.mrkr)
elseif a:item.type == 2
for ki in ['d', 'u', 'l']
let match = matchstr(a:item.mrkr, '\'.ki.'\+['.s:number_divisors.']')
if match != ''
return '\'.ki.'\+'.vimwiki#u#escape(match[-1:])
endif
endfor
else
return ''
endif
endfunction "}}}
2014-01-06 13:30:33 +01:00
"get properties of an item }}}
"functions for navigating between items {{{
"Returns: the list item after a:item or an empty item
"If a:ignore_kind is 1, the markers can differ
function! s:get_next_list_item(item, ignore_kind) "{{{
let org_lvl = s:get_level(a:item.lnum)
if !a:ignore_kind
let org_regex = s:regexp_of_marker(a:item)
endif
let cur_ln = s:get_next_line(a:item.lnum)
while cur_ln <= line('$')
let cur_lvl = s:get_level(cur_ln)
if cur_lvl <= org_lvl
if a:ignore_kind
return s:get_any_item_of_level(cur_ln, cur_lvl, org_lvl)
else
return s:get_item_of_level(cur_ln, cur_lvl, org_lvl, org_regex)
endif
endif
let cur_ln = s:get_next_line(cur_ln)
endwhile
return s:empty_item()
endfunction "}}}
"Returns: the list item before a:item or an empty item
"If a:ignore_kind is 1, the markers can differ
function! s:get_prev_list_item(item, ignore_kind) "{{{
let org_lvl = s:get_level(a:item.lnum)
if !a:ignore_kind
let org_regex = s:regexp_of_marker(a:item)
endif
let cur_ln = s:get_prev_line(a:item.lnum)
while cur_ln >= 1
let cur_lvl = s:get_level(cur_ln)
if cur_lvl <= org_lvl
if a:ignore_kind
return s:get_any_item_of_level(cur_ln, cur_lvl, org_lvl)
else
return s:get_item_of_level(cur_ln, cur_lvl, org_lvl, org_regex)
endif
endif
let cur_ln = s:get_prev_line(cur_ln)
endwhile
return s:empty_item()
endfunction "}}}
function! s:get_item_of_level(cur_ln, cur_lvl, org_lvl, org_regex) "{{{
let cur_linecontent = getline(a:cur_ln)
if a:cur_lvl == a:org_lvl
if cur_linecontent =~# '^\s*'.a:org_regex.'\s'
return s:get_item(a:cur_ln)
else
return s:empty_item()
endif
elseif a:cur_lvl < a:org_lvl
return s:empty_item()
endif
endfunction "}}}
function! s:get_any_item_of_level(cur_ln, cur_lvl, org_lvl) "{{{
if a:cur_lvl == a:org_lvl
return s:get_item(a:cur_ln)
elseif a:cur_lvl < a:org_lvl
return s:empty_item()
endif
endfunction "}}}
function! s:get_first_item_in_list(item, ignore_kind) "{{{
let cur_item = a:item
while 1
let prev_item = s:get_prev_list_item(cur_item, a:ignore_kind)
if prev_item.type == 0
break
else
let cur_item = prev_item
endif
endwhile
return cur_item
endfunction "}}}
function! s:get_last_item_in_list(item, ignore_kind) "{{{
let cur_item = a:item
while 1
let next_item = s:get_next_list_item(cur_item, a:ignore_kind)
if next_item.type == 0
break
else
let cur_item = next_item
endif
endwhile
return cur_item
endfunction "}}}
"Returns: lnum+1 in most cases, but skips blank lines and preformatted text,
"0 in case of nonvalid line.
"If there is no second argument, 0 is returned at a header, otherwise the
"header is skipped
function! s:get_next_line(lnum, ...) "{{{
2016-03-18 15:16:59 +01:00
if getline(a:lnum) =~# g:vimwiki_rxPreStart
let cur_ln = a:lnum + 1
while cur_ln <= line('$') &&
2016-03-18 15:16:59 +01:00
\ getline(cur_ln) !~# g:vimwiki_rxPreEnd
let cur_ln += 1
endwhile
let next_line = cur_ln
else
let next_line = nextnonblank(a:lnum+1)
endif
if a:0 > 0 && getline(next_line) =~# g:vimwiki_rxHeader
let next_line = s:get_next_line(next_line, 1)
endif
if next_line < 0 || next_line > line('$') ||
\ (getline(next_line) =~# g:vimwiki_rxHeader && a:0 == 0)
return 0
endif
return next_line
endfunction "}}}
"Returns: lnum-1 in most cases, but skips blank lines and preformatted text
"0 in case of nonvalid line and a header, because a header ends every list
function! s:get_prev_line(lnum) "{{{
let prev_line = prevnonblank(a:lnum-1)
2016-03-18 15:16:59 +01:00
if getline(prev_line) =~# g:vimwiki_rxPreEnd
let cur_ln = a:lnum - 1
while 1
2016-03-18 15:16:59 +01:00
if cur_ln == 0 || getline(cur_ln) =~# g:vimwiki_rxPreStart
break
endif
let cur_ln -= 1
endwhile
let prev_line = cur_ln
endif
if prev_line < 0 || prev_line > line('$') ||
\ getline(prev_line) =~# g:vimwiki_rxHeader
return 0
endif
return prev_line
endfunction "}}}
function! s:get_first_child(item) "{{{
if a:item.lnum >= line('$')
return s:empty_item()
endif
let org_lvl = s:get_level(a:item.lnum)
let cur_item = s:get_item(s:get_next_line(a:item.lnum))
while 1
if cur_item.type != 0 && s:get_level(cur_item.lnum) > org_lvl
return cur_item
endif
if cur_item.lnum > line('$') || cur_item.lnum <= 0 ||
\ s:get_level(cur_item.lnum) <= org_lvl
return s:empty_item()
endif
let cur_item = s:get_item(s:get_next_line(cur_item.lnum))
endwhile
endfunction "}}}
"Returns: the next sibling of a:child, given the parent item
"Used for iterating over children
"Note: child items do not necessarily have the same indent, i.e. level
function! s:get_next_child_item(parent, child) "{{{
if a:parent.type == 0 | return s:empty_item() | endif
let parent_lvl = s:get_level(a:parent.lnum)
let cur_ln = s:get_last_line_of_item_incl_children(a:child)
while 1
let next_line = s:get_next_line(cur_ln)
if next_line == 0 || s:get_level(next_line) <= parent_lvl
break
endif
let cur_ln = next_line
let cur_item = s:get_item(cur_ln)
if cur_item.type > 0
return cur_item
endif
endwhile
return s:empty_item()
endfunction "}}}
function! s:get_parent(item) "{{{
let parent_line = 0
let cur_ln = prevnonblank(a:item.lnum)
let child_lvl = s:get_level(cur_ln)
if child_lvl == 0
return s:empty_item()
endif
while 1
let cur_ln = s:get_prev_line(cur_ln)
if cur_ln == 0 | break | endif
let cur_lvl = s:get_level(cur_ln)
if cur_lvl < child_lvl
let cur_item = s:get_item(cur_ln)
if cur_item.type == 0
let child_lvl = cur_lvl
continue
endif
let parent_line = cur_ln
break
endif
endwhile
return s:get_item(parent_line)
endfunction "}}}
2014-01-06 13:30:33 +01:00
"Returns: the item above or the item below or an empty item
function! s:get_a_neighbor_item(item) "{{{
let prev_item = s:get_prev_list_item(a:item, 1)
if prev_item.type != 0
return prev_item
else
let next_item = s:get_next_list_item(a:item, 1)
if next_item.type != 0
return next_item
endif
endif
return s:empty_item()
endfunction "}}}
function! s:get_a_neighbor_item_in_column(lnum, column) "{{{
let cur_ln = s:get_prev_line(a:lnum)
while cur_ln >= 1
if s:get_level(cur_ln) <= a:column
return s:get_corresponding_item(cur_ln)
endif
let cur_ln = s:get_prev_line(cur_ln)
endwhile
return s:empty_item()
endfunction "}}}
"Returns: the item if there is one in a:lnum
"else the multiline item a:lnum belongs to
function! s:get_corresponding_item(lnum) "{{{
let item = s:get_item(a:lnum)
if item.type != 0
return item
endif
let org_lvl = s:get_level(a:lnum)
let cur_ln = a:lnum
while cur_ln > 0
let cur_lvl = s:get_level(cur_ln)
let cur_item = s:get_item(cur_ln)
if cur_lvl < org_lvl && cur_item.type != 0
return cur_item
endif
if cur_lvl < org_lvl
let org_lvl = cur_lvl
endif
let cur_ln = s:get_prev_line(cur_ln)
endwhile
return s:empty_item()
endfunction "}}}
"Returns: the last line of a (possibly multiline) item, including all children
function! s:get_last_line_of_item_incl_children(item) "{{{
let cur_ln = a:item.lnum
let org_lvl = s:get_level(a:item.lnum)
while 1
let next_line = s:get_next_line(cur_ln)
if next_line == 0 || s:get_level(next_line) <= org_lvl
return cur_ln
endif
let cur_ln = next_line
endwhile
endfunction "}}}
"Returns: the last line of a (possibly multiline) item
"Note: there can be other list items between the first and last line
2014-01-06 13:30:33 +01:00
function! s:get_last_line_of_item(item) "{{{
if a:item.type == 0 | return 0 | endif
let org_lvl = s:get_level(a:item.lnum)
let last_corresponding_line = a:item.lnum
let cur_ln = s:get_next_line(a:item.lnum)
while 1
if cur_ln == 0 || s:get_level(cur_ln) <= org_lvl
break
endif
let cur_item = s:get_item(cur_ln)
if cur_item.type == 0
let last_corresponding_line = cur_ln
let cur_ln = s:get_next_line(cur_ln)
else
let cur_ln = s:get_next_line(
\ s:get_last_line_of_item_incl_children(cur_item))
endif
endwhile
return last_corresponding_line
endfunction "}}}
"functions for navigating between items }}}
"renumber list items {{{
"Renumbers the current list from a:item on downwards
"Returns: the last item that was adjusted
function! s:adjust_numbered_list_below(item, recursive) "{{{
if !(a:item.type == 2 || (a:item.type == 1 && a:recursive))
return a:item
endif
let kind = s:guess_kind_of_numbered_item(a:item)
let cur_item = a:item
while 1
if a:recursive
call s:adjust_items_recursively(cur_item)
endif
let next_item = s:get_next_list_item(cur_item, 0)
if next_item.type == 0
break
endif
if cur_item.type == 2
let new_val = s:increment_{kind}(cur_item.mrkr[:-2]) . cur_item.mrkr[-1:]
call s:substitute_string_in_line(next_item.lnum, next_item.mrkr, new_val)
let next_item.mrkr = new_val
endif
let cur_item = next_item
endwhile
return cur_item
endfunction "}}}
function! s:adjust_items_recursively(parent) "{{{
if a:parent.type == 0
return s:empty_item()
end
let child_item = s:get_first_child(a:parent)
if child_item.type == 0
return child_item
endif
while 1
let last_item = s:adjust_numbered_list(child_item, 1, 1)
let child_item = s:get_next_child_item(a:parent, last_item)
if child_item.type == 0
return last_item
endif
endwhile
endfunction "}}}
"Renumbers the list a:item is in.
"If a:ignore_kind == 0, only the items which have the same kind of marker as
"a:item are considered, otherwise all items.
"Returns: the last item that was adjusted
function! s:adjust_numbered_list(item, ignore_kind, recursive) "{{{
if !(a:item.type == 2 || (a:item.type == 1 && (a:ignore_kind || a:recursive)))
return s:empty_item()
end
let first_item = s:get_first_item_in_list(a:item, a:ignore_kind)
while 1
if first_item.type == 2
let new_mrkr = s:guess_kind_of_numbered_item(first_item) .
\ first_item.mrkr[-1:]
call s:substitute_string_in_line(first_item.lnum, first_item.mrkr,
\ new_mrkr)
let first_item.mrkr = new_mrkr
endif
let last_item = s:adjust_numbered_list_below(first_item, a:recursive)
let next_first_item = s:get_next_list_item(last_item, 1)
if a:ignore_kind == 0 || next_first_item.type == 0
return last_item
endif
let first_item = next_first_item
endwhile
endfunction "}}}
2014-01-06 13:30:33 +01:00
"Renumbers the list the cursor is in
"also update its parents checkbox state
function! vimwiki#lst#adjust_numbered_list() "{{{
let cur_item = s:get_corresponding_item(line('.'))
if cur_item.type == 0 | return | endif
call s:adjust_numbered_list(cur_item, 1, 0)
call s:update_state(s:get_parent(cur_item))
endfunction "}}}
2014-01-06 13:30:33 +01:00
"Renumbers all lists of the buffer
"of course, this might take some seconds
function! vimwiki#lst#adjust_whole_buffer() "{{{
let cur_ln = 1
while 1
let cur_item = s:get_item(cur_ln)
if cur_item.type != 0
let cur_item = s:adjust_numbered_list(cur_item, 0, 1)
endif
let cur_ln = s:get_next_line(cur_item.lnum, 1)
if cur_ln <= 0 || cur_ln > line('$')
return
endif
endwhile
endfunction "}}}
"renumber list items }}}
"checkbox stuff {{{
"Returns: the rate of checkboxed list item in percent
function! s:get_rate(item) "{{{
if a:item.type == 0 || a:item.cb == ''
return -1
endif
let state = a:item.cb
return index(g:vimwiki_listsyms_list, state) * 25
endfunction "}}}
"Set state of the list item to [ ] or [o] or whatever
"Returns: 1 if the state changed, 0 otherwise
function! s:set_state(item, new_rate) "{{{
let new_state = s:rate_to_state(a:new_rate)
let old_state = s:rate_to_state(s:get_rate(a:item))
if new_state !=# old_state
call s:substitute_rx_in_line(a:item.lnum, '\[.]', '['.new_state.']')
return 1
else
return 0
endif
endfunction "}}}
"Set state of the list item to [ ] or [o] or whatever
"Updates the states of its child items
function! s:set_state_plus_children(item, new_rate) "{{{
call s:set_state(a:item, a:new_rate)
let child_item = s:get_first_child(a:item)
while 1
if child_item.type == 0
break
endif
if child_item.cb != ''
call s:set_state_plus_children(child_item, a:new_rate)
endif
let child_item = s:get_next_child_item(a:item, child_item)
endwhile
endfunction "}}}
"Returns: the appropriate symbol for a given percent rate
function! s:rate_to_state(rate) "{{{
let state = ''
if a:rate == 100
let state = g:vimwiki_listsyms_list[4]
elseif a:rate == 0
let state = g:vimwiki_listsyms_list[0]
elseif a:rate >= 67
let state = g:vimwiki_listsyms_list[3]
elseif a:rate >= 34
let state = g:vimwiki_listsyms_list[2]
else
let state = g:vimwiki_listsyms_list[1]
endif
return state
endfunction "}}}
"updates the symbol of a checkboxed item according to the symbols of its
"children
function! s:update_state(item) "{{{
if a:item.type == 0 || a:item.cb == ''
return
endif
let sum_children_rate = 0
let count_children_with_cb = 0
let child_item = s:get_first_child(a:item)
while 1
if child_item.type == 0
break
endif
if child_item.cb != ''
let count_children_with_cb += 1
let sum_children_rate += s:get_rate(child_item)
endif
let child_item = s:get_next_child_item(a:item, child_item)
endwhile
if count_children_with_cb > 0
let new_rate = sum_children_rate / count_children_with_cb
call s:set_state_recursively(a:item, new_rate)
else
let rate = s:get_rate(a:item)
if rate > 0 && rate < 100
call s:set_state_recursively(a:item, 0)
endif
endif
endfunction "}}}
function! s:set_state_recursively(item, new_rate) "{{{
let state_changed = s:set_state(a:item, a:new_rate)
if state_changed
call s:update_state(s:get_parent(a:item))
endif
endfunction "}}}
"Creates checkbox in a list item.
"Returns: 1 if successful
function! s:create_cb(item) "{{{
if a:item.type == 0 || a:item.cb != ''
return 0
endif
let new_item = a:item
let new_item.cb = g:vimwiki_listsyms_list[0]
call s:substitute_rx_in_line(new_item.lnum,
\ vimwiki#u#escape(new_item.mrkr) . '\zs\ze', ' [' . new_item.cb . ']')
call s:update_state(new_item)
return 1
endfunction "}}}
function! s:remove_cb(item) "{{{
let item = a:item
if item.type != 0 && item.cb != ''
let item.cb = ''
call s:substitute_rx_in_line(item.lnum, '\s\+\[.\]', '')
endif
return item
endfunction "}}}
"Toggles checkbox between [ ] and [X] or creates one
"in the lines of the given range
2014-01-06 13:54:11 +01:00
function! vimwiki#lst#toggle_cb(from_line, to_line) "{{{
let from_item = s:get_corresponding_item(a:from_line)
if from_item.type == 0
return
endif
let parent_items_of_lines = []
if from_item.cb == ''
2014-01-06 13:54:11 +01:00
"if from_line has no CB, make a CB in every selected line
let parent_items_of_lines = []
2014-01-06 13:54:11 +01:00
for cur_ln in range(from_item.lnum, a:to_line)
let cur_item = s:get_item(cur_ln)
let success = s:create_cb(cur_item)
if success
let cur_parent_item = s:get_parent(cur_item)
if index(parent_items_of_lines, cur_parent_item) == -1
call insert(parent_items_of_lines, cur_parent_item)
endif
endif
endfor
else
2014-01-06 13:54:11 +01:00
"if from_line has CB, toggle it and set all siblings to the same new state
let rate_first_line = s:get_rate(from_item)
let new_rate = rate_first_line == 100 ? 0 : 100
2014-01-06 13:54:11 +01:00
for cur_ln in range(from_item.lnum, a:to_line)
let cur_item = s:get_item(cur_ln)
if cur_item.type != 0 && cur_item.cb != ''
call s:set_state_plus_children(cur_item, new_rate)
let cur_parent_item = s:get_parent(cur_item)
if index(parent_items_of_lines, cur_parent_item) == -1
call insert(parent_items_of_lines, cur_parent_item)
endif
endif
endfor
endif
for parent_item in parent_items_of_lines
call s:update_state(parent_item)
endfor
endfunction "}}}
function! vimwiki#lst#remove_cb(first_line, last_line) "{{{
let first_item = s:get_corresponding_item(a:first_line)
let last_item = s:get_corresponding_item(a:last_line)
if first_item.type == 0 || last_item.type == 0
return
endif
Version 1.2 = Note = Remove previous version of vimwiki before install - files in autoload dir is moved/renamed to autoload/vimwiki dir. = Changelog = * Issue 70: Table spanning cell support. * Issue 72: Do not convert again for unchanged file. |:VimwikiAll2HTML| converts only changed wiki files. * Issue 117: |VimwikiDiaryIndex| command that opens diary index wiki page. * Issue 120: Links in headers are not highlighted in vimwiki but are highlighted in HTML. * Issue 138: Added possibility to remap table-column move bindings. See |:VimwikiTableMoveColumnLeft| and |:VimwikiTableMoveColumnRight| commands. For remap instructions see |vimwiki_<A-Left>| and |vimwiki_<A-Right>|. * Issue 125: Problem with 'o' command given while at the of the file. * Issue 131: FileType is not set up when GUIEnter autocommand is used in vimrc. Use 'nested' in 'au GUIEnter * nested VimwikiIndex' * Issue 132: Link to perl (or any non-wiki) file in vimwiki subdirectory doesn't work as intended. * Issue 135: %title and %toc used together cause TOC to appear in an unexpected place in HTML. * Issue 139: |:VimwikiTabnewLink| command is added. * Fix of g:vimwiki_stripsym = '' (i.e. an empty string) -- it removes bad symbols from filenames. * Issue 145: With modeline 'set ft=vimwiki' links are not correctly highlighted when open wiki files. * Issue 146: Filetype difficulty with ".txt" as a vimwiki extension. * Issue 148: There are no mailto links. * Issue 151: Use location list instead of quickfix list for :VimwikiSearch command result. Use :lopen instead of :copen, :lnext instead of :cnext etc. * Issue 152: Add the list of HTML files that would not be deleted after |:VimwikiAll2HTML|. * Issue 153: Delete HTML files that has no corresponding wiki ones with |:VimwikiAll2HTML|. * Issue 156: Add multiple HTML templates. See |vimwiki-option-template_path|. Options html_header and html_footer are no longer exist. * Issue 173: When virtualedit=all option is enabled the 'o' command behave strange. * Issue 178: Problem with alike wikie's paths. * Issue 182: Browser command does not quote url. * Issue 183: Spelling error highlighting is not possible with nested syntaxes. * Issue 184: Wrong foldlevel in some cases. * Issue 195: Page renaming issue. * Issue 196: vim: modeline bug -- syn=vim doesn't work. * Issue 199: Generated HTML for sublists is invalid. * Issue 200: Generated HTML for todo lists does not show completion status the fix relies on CSS, thus your old stylesheets need to be updated!; may not work in obsolete browsers or font-deficient systems. * Issue 205: Block code: highlighting differs from processing. Inline code block {{{ ... }}} is removed. Use `...` instead. * Issue 208: Default highlight colors are problematic in many colorschemes. Headers are highlighted as |hl-Title| by default, use |g:vimwiki_hl_headers| to restore previous default Red, Green, Blue or custom header colors. Some other changes in highlighting. * Issue 209: Wild comments slow down html generation. Comments are changed, use %% to comment out entire line. * Issue 210: HTML: para enclose header. * Issue 214: External links containing Chinese characters get trimmed. * Issue 218: Command to generate HTML file and open it in webbrowser. See |:Vimwiki2HTMLBrowse|(bind to <leader>whh) * NEW: Added <Leader>wh mapping to call |:Vimwiki2HTML|
2011-06-11 02:00:00 +02:00
let parent_items_of_lines = []
let cur_ln = first_item.lnum
while 1
if cur_ln <= 0 || cur_ln > last_item.lnum | break | endif
let cur_item = s:get_item(cur_ln)
if cur_item.type != 0
let cur_item = s:remove_cb(cur_item)
let cur_parent_item = s:get_parent(cur_item)
if index(parent_items_of_lines, cur_parent_item) == -1
call insert(parent_items_of_lines, cur_parent_item)
endif
Version 1.2 = Note = Remove previous version of vimwiki before install - files in autoload dir is moved/renamed to autoload/vimwiki dir. = Changelog = * Issue 70: Table spanning cell support. * Issue 72: Do not convert again for unchanged file. |:VimwikiAll2HTML| converts only changed wiki files. * Issue 117: |VimwikiDiaryIndex| command that opens diary index wiki page. * Issue 120: Links in headers are not highlighted in vimwiki but are highlighted in HTML. * Issue 138: Added possibility to remap table-column move bindings. See |:VimwikiTableMoveColumnLeft| and |:VimwikiTableMoveColumnRight| commands. For remap instructions see |vimwiki_<A-Left>| and |vimwiki_<A-Right>|. * Issue 125: Problem with 'o' command given while at the of the file. * Issue 131: FileType is not set up when GUIEnter autocommand is used in vimrc. Use 'nested' in 'au GUIEnter * nested VimwikiIndex' * Issue 132: Link to perl (or any non-wiki) file in vimwiki subdirectory doesn't work as intended. * Issue 135: %title and %toc used together cause TOC to appear in an unexpected place in HTML. * Issue 139: |:VimwikiTabnewLink| command is added. * Fix of g:vimwiki_stripsym = '' (i.e. an empty string) -- it removes bad symbols from filenames. * Issue 145: With modeline 'set ft=vimwiki' links are not correctly highlighted when open wiki files. * Issue 146: Filetype difficulty with ".txt" as a vimwiki extension. * Issue 148: There are no mailto links. * Issue 151: Use location list instead of quickfix list for :VimwikiSearch command result. Use :lopen instead of :copen, :lnext instead of :cnext etc. * Issue 152: Add the list of HTML files that would not be deleted after |:VimwikiAll2HTML|. * Issue 153: Delete HTML files that has no corresponding wiki ones with |:VimwikiAll2HTML|. * Issue 156: Add multiple HTML templates. See |vimwiki-option-template_path|. Options html_header and html_footer are no longer exist. * Issue 173: When virtualedit=all option is enabled the 'o' command behave strange. * Issue 178: Problem with alike wikie's paths. * Issue 182: Browser command does not quote url. * Issue 183: Spelling error highlighting is not possible with nested syntaxes. * Issue 184: Wrong foldlevel in some cases. * Issue 195: Page renaming issue. * Issue 196: vim: modeline bug -- syn=vim doesn't work. * Issue 199: Generated HTML for sublists is invalid. * Issue 200: Generated HTML for todo lists does not show completion status the fix relies on CSS, thus your old stylesheets need to be updated!; may not work in obsolete browsers or font-deficient systems. * Issue 205: Block code: highlighting differs from processing. Inline code block {{{ ... }}} is removed. Use `...` instead. * Issue 208: Default highlight colors are problematic in many colorschemes. Headers are highlighted as |hl-Title| by default, use |g:vimwiki_hl_headers| to restore previous default Red, Green, Blue or custom header colors. Some other changes in highlighting. * Issue 209: Wild comments slow down html generation. Comments are changed, use %% to comment out entire line. * Issue 210: HTML: para enclose header. * Issue 214: External links containing Chinese characters get trimmed. * Issue 218: Command to generate HTML file and open it in webbrowser. See |:Vimwiki2HTMLBrowse|(bind to <leader>whh) * NEW: Added <Leader>wh mapping to call |:Vimwiki2HTML|
2011-06-11 02:00:00 +02:00
endif
let cur_ln = s:get_next_line(cur_ln)
endwhile
for parent_item in parent_items_of_lines
call s:update_state(parent_item)
endfor
endfunction "}}}
Version 1.2 = Note = Remove previous version of vimwiki before install - files in autoload dir is moved/renamed to autoload/vimwiki dir. = Changelog = * Issue 70: Table spanning cell support. * Issue 72: Do not convert again for unchanged file. |:VimwikiAll2HTML| converts only changed wiki files. * Issue 117: |VimwikiDiaryIndex| command that opens diary index wiki page. * Issue 120: Links in headers are not highlighted in vimwiki but are highlighted in HTML. * Issue 138: Added possibility to remap table-column move bindings. See |:VimwikiTableMoveColumnLeft| and |:VimwikiTableMoveColumnRight| commands. For remap instructions see |vimwiki_<A-Left>| and |vimwiki_<A-Right>|. * Issue 125: Problem with 'o' command given while at the of the file. * Issue 131: FileType is not set up when GUIEnter autocommand is used in vimrc. Use 'nested' in 'au GUIEnter * nested VimwikiIndex' * Issue 132: Link to perl (or any non-wiki) file in vimwiki subdirectory doesn't work as intended. * Issue 135: %title and %toc used together cause TOC to appear in an unexpected place in HTML. * Issue 139: |:VimwikiTabnewLink| command is added. * Fix of g:vimwiki_stripsym = '' (i.e. an empty string) -- it removes bad symbols from filenames. * Issue 145: With modeline 'set ft=vimwiki' links are not correctly highlighted when open wiki files. * Issue 146: Filetype difficulty with ".txt" as a vimwiki extension. * Issue 148: There are no mailto links. * Issue 151: Use location list instead of quickfix list for :VimwikiSearch command result. Use :lopen instead of :copen, :lnext instead of :cnext etc. * Issue 152: Add the list of HTML files that would not be deleted after |:VimwikiAll2HTML|. * Issue 153: Delete HTML files that has no corresponding wiki ones with |:VimwikiAll2HTML|. * Issue 156: Add multiple HTML templates. See |vimwiki-option-template_path|. Options html_header and html_footer are no longer exist. * Issue 173: When virtualedit=all option is enabled the 'o' command behave strange. * Issue 178: Problem with alike wikie's paths. * Issue 182: Browser command does not quote url. * Issue 183: Spelling error highlighting is not possible with nested syntaxes. * Issue 184: Wrong foldlevel in some cases. * Issue 195: Page renaming issue. * Issue 196: vim: modeline bug -- syn=vim doesn't work. * Issue 199: Generated HTML for sublists is invalid. * Issue 200: Generated HTML for todo lists does not show completion status the fix relies on CSS, thus your old stylesheets need to be updated!; may not work in obsolete browsers or font-deficient systems. * Issue 205: Block code: highlighting differs from processing. Inline code block {{{ ... }}} is removed. Use `...` instead. * Issue 208: Default highlight colors are problematic in many colorschemes. Headers are highlighted as |hl-Title| by default, use |g:vimwiki_hl_headers| to restore previous default Red, Green, Blue or custom header colors. Some other changes in highlighting. * Issue 209: Wild comments slow down html generation. Comments are changed, use %% to comment out entire line. * Issue 210: HTML: para enclose header. * Issue 214: External links containing Chinese characters get trimmed. * Issue 218: Command to generate HTML file and open it in webbrowser. See |:Vimwiki2HTMLBrowse|(bind to <leader>whh) * NEW: Added <Leader>wh mapping to call |:Vimwiki2HTML|
2011-06-11 02:00:00 +02:00
function! vimwiki#lst#remove_cb_in_list() "{{{
let first_item = s:get_first_item_in_list(
\ s:get_corresponding_item(line('.')), 0)
Version 1.2 = Note = Remove previous version of vimwiki before install - files in autoload dir is moved/renamed to autoload/vimwiki dir. = Changelog = * Issue 70: Table spanning cell support. * Issue 72: Do not convert again for unchanged file. |:VimwikiAll2HTML| converts only changed wiki files. * Issue 117: |VimwikiDiaryIndex| command that opens diary index wiki page. * Issue 120: Links in headers are not highlighted in vimwiki but are highlighted in HTML. * Issue 138: Added possibility to remap table-column move bindings. See |:VimwikiTableMoveColumnLeft| and |:VimwikiTableMoveColumnRight| commands. For remap instructions see |vimwiki_<A-Left>| and |vimwiki_<A-Right>|. * Issue 125: Problem with 'o' command given while at the of the file. * Issue 131: FileType is not set up when GUIEnter autocommand is used in vimrc. Use 'nested' in 'au GUIEnter * nested VimwikiIndex' * Issue 132: Link to perl (or any non-wiki) file in vimwiki subdirectory doesn't work as intended. * Issue 135: %title and %toc used together cause TOC to appear in an unexpected place in HTML. * Issue 139: |:VimwikiTabnewLink| command is added. * Fix of g:vimwiki_stripsym = '' (i.e. an empty string) -- it removes bad symbols from filenames. * Issue 145: With modeline 'set ft=vimwiki' links are not correctly highlighted when open wiki files. * Issue 146: Filetype difficulty with ".txt" as a vimwiki extension. * Issue 148: There are no mailto links. * Issue 151: Use location list instead of quickfix list for :VimwikiSearch command result. Use :lopen instead of :copen, :lnext instead of :cnext etc. * Issue 152: Add the list of HTML files that would not be deleted after |:VimwikiAll2HTML|. * Issue 153: Delete HTML files that has no corresponding wiki ones with |:VimwikiAll2HTML|. * Issue 156: Add multiple HTML templates. See |vimwiki-option-template_path|. Options html_header and html_footer are no longer exist. * Issue 173: When virtualedit=all option is enabled the 'o' command behave strange. * Issue 178: Problem with alike wikie's paths. * Issue 182: Browser command does not quote url. * Issue 183: Spelling error highlighting is not possible with nested syntaxes. * Issue 184: Wrong foldlevel in some cases. * Issue 195: Page renaming issue. * Issue 196: vim: modeline bug -- syn=vim doesn't work. * Issue 199: Generated HTML for sublists is invalid. * Issue 200: Generated HTML for todo lists does not show completion status the fix relies on CSS, thus your old stylesheets need to be updated!; may not work in obsolete browsers or font-deficient systems. * Issue 205: Block code: highlighting differs from processing. Inline code block {{{ ... }}} is removed. Use `...` instead. * Issue 208: Default highlight colors are problematic in many colorschemes. Headers are highlighted as |hl-Title| by default, use |g:vimwiki_hl_headers| to restore previous default Red, Green, Blue or custom header colors. Some other changes in highlighting. * Issue 209: Wild comments slow down html generation. Comments are changed, use %% to comment out entire line. * Issue 210: HTML: para enclose header. * Issue 214: External links containing Chinese characters get trimmed. * Issue 218: Command to generate HTML file and open it in webbrowser. See |:Vimwiki2HTMLBrowse|(bind to <leader>whh) * NEW: Added <Leader>wh mapping to call |:Vimwiki2HTML|
2011-06-11 02:00:00 +02:00
let cur_item = first_item
while 1
let next_item = s:get_next_list_item(cur_item, 0)
let cur_item = s:remove_cb(cur_item)
if next_item.type == 0
break
Version 1.2 = Note = Remove previous version of vimwiki before install - files in autoload dir is moved/renamed to autoload/vimwiki dir. = Changelog = * Issue 70: Table spanning cell support. * Issue 72: Do not convert again for unchanged file. |:VimwikiAll2HTML| converts only changed wiki files. * Issue 117: |VimwikiDiaryIndex| command that opens diary index wiki page. * Issue 120: Links in headers are not highlighted in vimwiki but are highlighted in HTML. * Issue 138: Added possibility to remap table-column move bindings. See |:VimwikiTableMoveColumnLeft| and |:VimwikiTableMoveColumnRight| commands. For remap instructions see |vimwiki_<A-Left>| and |vimwiki_<A-Right>|. * Issue 125: Problem with 'o' command given while at the of the file. * Issue 131: FileType is not set up when GUIEnter autocommand is used in vimrc. Use 'nested' in 'au GUIEnter * nested VimwikiIndex' * Issue 132: Link to perl (or any non-wiki) file in vimwiki subdirectory doesn't work as intended. * Issue 135: %title and %toc used together cause TOC to appear in an unexpected place in HTML. * Issue 139: |:VimwikiTabnewLink| command is added. * Fix of g:vimwiki_stripsym = '' (i.e. an empty string) -- it removes bad symbols from filenames. * Issue 145: With modeline 'set ft=vimwiki' links are not correctly highlighted when open wiki files. * Issue 146: Filetype difficulty with ".txt" as a vimwiki extension. * Issue 148: There are no mailto links. * Issue 151: Use location list instead of quickfix list for :VimwikiSearch command result. Use :lopen instead of :copen, :lnext instead of :cnext etc. * Issue 152: Add the list of HTML files that would not be deleted after |:VimwikiAll2HTML|. * Issue 153: Delete HTML files that has no corresponding wiki ones with |:VimwikiAll2HTML|. * Issue 156: Add multiple HTML templates. See |vimwiki-option-template_path|. Options html_header and html_footer are no longer exist. * Issue 173: When virtualedit=all option is enabled the 'o' command behave strange. * Issue 178: Problem with alike wikie's paths. * Issue 182: Browser command does not quote url. * Issue 183: Spelling error highlighting is not possible with nested syntaxes. * Issue 184: Wrong foldlevel in some cases. * Issue 195: Page renaming issue. * Issue 196: vim: modeline bug -- syn=vim doesn't work. * Issue 199: Generated HTML for sublists is invalid. * Issue 200: Generated HTML for todo lists does not show completion status the fix relies on CSS, thus your old stylesheets need to be updated!; may not work in obsolete browsers or font-deficient systems. * Issue 205: Block code: highlighting differs from processing. Inline code block {{{ ... }}} is removed. Use `...` instead. * Issue 208: Default highlight colors are problematic in many colorschemes. Headers are highlighted as |hl-Title| by default, use |g:vimwiki_hl_headers| to restore previous default Red, Green, Blue or custom header colors. Some other changes in highlighting. * Issue 209: Wild comments slow down html generation. Comments are changed, use %% to comment out entire line. * Issue 210: HTML: para enclose header. * Issue 214: External links containing Chinese characters get trimmed. * Issue 218: Command to generate HTML file and open it in webbrowser. See |:Vimwiki2HTMLBrowse|(bind to <leader>whh) * NEW: Added <Leader>wh mapping to call |:Vimwiki2HTML|
2011-06-11 02:00:00 +02:00
else
let cur_item = next_item
Version 1.2 = Note = Remove previous version of vimwiki before install - files in autoload dir is moved/renamed to autoload/vimwiki dir. = Changelog = * Issue 70: Table spanning cell support. * Issue 72: Do not convert again for unchanged file. |:VimwikiAll2HTML| converts only changed wiki files. * Issue 117: |VimwikiDiaryIndex| command that opens diary index wiki page. * Issue 120: Links in headers are not highlighted in vimwiki but are highlighted in HTML. * Issue 138: Added possibility to remap table-column move bindings. See |:VimwikiTableMoveColumnLeft| and |:VimwikiTableMoveColumnRight| commands. For remap instructions see |vimwiki_<A-Left>| and |vimwiki_<A-Right>|. * Issue 125: Problem with 'o' command given while at the of the file. * Issue 131: FileType is not set up when GUIEnter autocommand is used in vimrc. Use 'nested' in 'au GUIEnter * nested VimwikiIndex' * Issue 132: Link to perl (or any non-wiki) file in vimwiki subdirectory doesn't work as intended. * Issue 135: %title and %toc used together cause TOC to appear in an unexpected place in HTML. * Issue 139: |:VimwikiTabnewLink| command is added. * Fix of g:vimwiki_stripsym = '' (i.e. an empty string) -- it removes bad symbols from filenames. * Issue 145: With modeline 'set ft=vimwiki' links are not correctly highlighted when open wiki files. * Issue 146: Filetype difficulty with ".txt" as a vimwiki extension. * Issue 148: There are no mailto links. * Issue 151: Use location list instead of quickfix list for :VimwikiSearch command result. Use :lopen instead of :copen, :lnext instead of :cnext etc. * Issue 152: Add the list of HTML files that would not be deleted after |:VimwikiAll2HTML|. * Issue 153: Delete HTML files that has no corresponding wiki ones with |:VimwikiAll2HTML|. * Issue 156: Add multiple HTML templates. See |vimwiki-option-template_path|. Options html_header and html_footer are no longer exist. * Issue 173: When virtualedit=all option is enabled the 'o' command behave strange. * Issue 178: Problem with alike wikie's paths. * Issue 182: Browser command does not quote url. * Issue 183: Spelling error highlighting is not possible with nested syntaxes. * Issue 184: Wrong foldlevel in some cases. * Issue 195: Page renaming issue. * Issue 196: vim: modeline bug -- syn=vim doesn't work. * Issue 199: Generated HTML for sublists is invalid. * Issue 200: Generated HTML for todo lists does not show completion status the fix relies on CSS, thus your old stylesheets need to be updated!; may not work in obsolete browsers or font-deficient systems. * Issue 205: Block code: highlighting differs from processing. Inline code block {{{ ... }}} is removed. Use `...` instead. * Issue 208: Default highlight colors are problematic in many colorschemes. Headers are highlighted as |hl-Title| by default, use |g:vimwiki_hl_headers| to restore previous default Red, Green, Blue or custom header colors. Some other changes in highlighting. * Issue 209: Wild comments slow down html generation. Comments are changed, use %% to comment out entire line. * Issue 210: HTML: para enclose header. * Issue 214: External links containing Chinese characters get trimmed. * Issue 218: Command to generate HTML file and open it in webbrowser. See |:Vimwiki2HTMLBrowse|(bind to <leader>whh) * NEW: Added <Leader>wh mapping to call |:Vimwiki2HTML|
2011-06-11 02:00:00 +02:00
endif
endwhile
call s:update_state(s:get_parent(first_item))
endfunction "}}}
2014-01-06 13:30:33 +01:00
"checkbox stuff }}}
2014-01-06 13:30:33 +01:00
"change the level of list items {{{
function! s:set_indent(lnum, new_indent) "{{{
if &expandtab
let indentstring = repeat(' ', a:new_indent)
else
let indentstring = repeat('\t', a:new_indent / &tabstop) .
\ repeat(' ', a:new_indent % &tabstop)
endif
call s:substitute_rx_in_line(a:lnum, '^\s*', indentstring)
endfunction "}}}
function! s:decrease_level(item) "{{{
let removed_indent = 0
if VimwikiGet('syntax') ==? 'media' && a:item.type == 1 &&
\ index(s:multiple_bullet_chars, s:first_char(a:item.mrkr)) > -1
if s:string_length(a:item.mrkr) >= 2
call s:substitute_string_in_line(a:item.lnum,
\ s:first_char(a:item.mrkr), '')
let removed_indent = -1
endif
else
let old_indent = indent(a:item.lnum)
if &shiftround
let new_indent = (old_indent - 1) / vimwiki#u#sw() * vimwiki#u#sw()
else
let new_indent = old_indent - vimwiki#u#sw()
endif
call s:set_indent(a:item.lnum, new_indent)
let removed_indent = new_indent - old_indent
endif
return removed_indent
endfunction "}}}
function! s:increase_level(item) "{{{
let additional_indent = 0
if VimwikiGet('syntax') ==? 'media' && a:item.type == 1 &&
\ index(s:multiple_bullet_chars, s:first_char(a:item.mrkr)) > -1
call s:substitute_string_in_line(a:item.lnum, a:item.mrkr, a:item.mrkr .
\ s:first_char(a:item.mrkr))
let additional_indent = 1
else
let old_indent = indent(a:item.lnum)
if &shiftround
let new_indent = (old_indent / vimwiki#u#sw() + 1) * vimwiki#u#sw()
else
let new_indent = old_indent + vimwiki#u#sw()
endif
call s:set_indent(a:item.lnum, new_indent)
let additional_indent = new_indent - old_indent
endif
2014-01-06 13:30:33 +01:00
return additional_indent
endfunction "}}}
2014-01-06 13:30:33 +01:00
"adds a:indent_by to the current indent
"a:indent_by can be negative
function! s:indent_line_by(lnum, indent_by) "{{{
let item = s:get_item(a:lnum)
if VimwikiGet('syntax') ==? 'media' && item.type == 1 &&
2014-01-06 13:30:33 +01:00
\ index(s:multiple_bullet_chars, s:first_char(item.mrkr)) > -1
if a:indent_by > 0
call s:substitute_string_in_line(a:lnum, item.mrkr,
\ item.mrkr . s:first_char(item.mrkr))
elseif a:indent_by < 0
call s:substitute_string_in_line(a:lnum, s:first_char(item.mrkr), '')
endif
else
call s:set_indent(a:lnum, indent(a:lnum) + a:indent_by)
endif
endfunction "}}}
"changes lvl of lines in selection
function! s:change_level(from_line, to_line, direction, plus_children) "{{{
let from_item = s:get_corresponding_item(a:from_line)
if from_item.type == 0
if a:direction ==# 'increase' && a:from_line == a:to_line &&
\ empty(getline(a:from_line))
2013-10-29 13:06:02 +01:00
"that's because :> doesn't work on an empty line
normal! gi
else
execute a:from_line.','.a:to_line.(a:direction ==# 'increase' ? '>' : '<')
2013-10-29 13:06:02 +01:00
endif
return
endif
if a:direction ==# 'decrease' && s:get_level(from_item.lnum) == 0
2014-03-03 09:15:38 +01:00
return
endif
if a:from_line == a:to_line
if a:plus_children
let to_line = s:get_last_line_of_item_incl_children(from_item)
else
let to_line = s:get_last_line_of_item(from_item)
endif
else
let to_item = s:get_corresponding_item(a:to_line)
if to_item.type == 0
let to_line = a:to_line
else
if a:plus_children
let to_line = s:get_last_line_of_item_incl_children(to_item)
else
let to_line = s:get_last_line_of_item(to_item)
endif
endif
endif
if to_line == 0
return
endif
let to_be_adjusted = s:get_a_neighbor_item(from_item)
let old_parent = s:get_parent(from_item)
let first_line_level = s:get_level(from_item.lnum)
let more_than_one_level_concerned = 0
let first_line_indented_by =
\ (a:direction ==# 'increase') ?
\ s:increase_level(from_item) : s:decrease_level(from_item)
let cur_ln = s:get_next_line(from_item.lnum)
while cur_ln > 0 && cur_ln <= to_line
if !more_than_one_level_concerned &&
\ s:get_level(cur_ln) != first_line_level &&
\ s:get_item(cur_ln).type != 0
let more_than_one_level_concerned = 1
endif
call s:indent_line_by(cur_ln, first_line_indented_by)
let cur_ln = s:get_next_line(cur_ln, 1)
endwhile
2013-07-09 13:02:37 +02:00
if a:from_line == a:to_line
call s:adjust_mrkr(from_item)
endif
call s:update_state(old_parent)
let from_item = s:get_item(from_item.lnum)
if from_item.cb != ''
call s:update_state(from_item)
call s:update_state(s:get_parent(from_item))
endif
if more_than_one_level_concerned
call vimwiki#lst#adjust_whole_buffer()
else
2013-07-09 13:02:37 +02:00
call s:adjust_numbered_list(from_item, 0, 0)
call s:adjust_numbered_list(to_be_adjusted, 0, 0)
endif
endfunction "}}}
function! vimwiki#lst#change_level(from_line, to_line, direction, plus_children) "{{{
let cur_col = col('$') - col('.')
call s:change_level(a:from_line, a:to_line, a:direction, a:plus_children)
call cursor('.', col('$') - cur_col)
endfunction "}}}
2014-01-06 13:30:33 +01:00
"indent line a:lnum to be the continuation of a:prev_item
function! s:indent_multiline(prev_item, lnum) "{{{
if a:prev_item.type != 0
call s:set_indent(a:lnum, s:text_begin(a:prev_item.lnum))
endif
endfunction "}}}
"change the level of list items }}}
"change markers of list items {{{
"Returns: the position of a marker in g:vimwiki_list_markers
function! s:get_idx_list_markers(item) "{{{
if a:item.type == 1
let m = s:first_char(a:item.mrkr)
else
let m = s:guess_kind_of_numbered_item(a:item) . a:item.mrkr[-1:]
endif
return index(g:vimwiki_list_markers, m)
endfunction "}}}
"changes the marker of the given item to the next in g:vimwiki_list_markers
function! s:get_next_mrkr(item) "{{{
if a:item.type == 0
let new_mrkr = g:vimwiki_list_markers[0]
else
let idx = s:get_idx_list_markers(a:item)
let new_mrkr = g:vimwiki_list_markers[(idx+1) % len(g:vimwiki_list_markers)]
endif
return new_mrkr
endfunction "}}}
"changes the marker of the given item to the previous in g:vimwiki_list_markers
function! s:get_prev_mrkr(item) "{{{
if a:item.type == 0
return g:vimwiki_list_markers[-1]
endif
let idx = s:get_idx_list_markers(a:item)
if idx == -1
return g:vimwiki_list_markers[-1]
else
return g:vimwiki_list_markers[(idx - 1 + len(g:vimwiki_list_markers)) %
\ len(g:vimwiki_list_markers)]
endif
endfunction "}}}
function! s:set_new_mrkr(item, new_mrkr) "{{{
if a:item.type == 0
call s:substitute_rx_in_line(a:item.lnum, '^\s*\zs\ze', a:new_mrkr.' ')
if indent(a:item.lnum) == 0 && VimwikiGet('syntax') !=? 'media'
2014-01-06 13:30:33 +01:00
call s:set_indent(a:item.lnum, vimwiki#lst#get_list_margin())
endif
else
call s:substitute_string_in_line(a:item.lnum, a:item.mrkr, a:new_mrkr)
endif
endfunction "}}}
2014-01-06 13:54:11 +01:00
function! vimwiki#lst#change_marker(from_line, to_line, new_mrkr, mode) "{{{
let cur_col_from_eol = col("$") - (a:mode ==# "i" ? col("'^") : col('.'))
2014-01-06 13:30:33 +01:00
let new_mrkr = a:new_mrkr
2014-01-06 13:54:11 +01:00
let cur_ln = a:from_line
2014-01-06 13:30:33 +01:00
while 1
let cur_item = s:get_item(cur_ln)
if new_mrkr ==# "next"
let new_mrkr = s:get_next_mrkr(cur_item)
elseif new_mrkr ==# "prev"
let new_mrkr = s:get_prev_mrkr(cur_item)
endif
"handle markers like ***
if index(s:multiple_bullet_chars, s:first_char(new_mrkr)) > -1
"use *** if the item above has *** too
let item_above = s:get_prev_list_item(cur_item, 1)
if item_above.type == 1 &&
\ s:first_char(item_above.mrkr) ==# s:first_char(new_mrkr)
2014-01-06 13:30:33 +01:00
let new_mrkr = item_above.mrkr
else
"use *** if the item below has *** too
let item_below = s:get_next_list_item(cur_item, 1)
if item_below.type == 1 &&
\ s:first_char(item_below.mrkr) ==# s:first_char(new_mrkr)
2014-01-06 13:30:33 +01:00
let new_mrkr = item_below.mrkr
else
"if the old is ### and the new is * use ***
if cur_item.type == 1 &&
\ index(s:multiple_bullet_chars,s:first_char(cur_item.mrkr))>-1
let new_mrkr = repeat(new_mrkr, s:string_length(cur_item.mrkr))
else
"use *** if the parent item has **
let parent_item = s:get_parent(cur_item)
if parent_item.type == 1 &&
\ s:first_char(parent_item.mrkr) ==# s:first_char(new_mrkr)
2014-01-06 13:30:33 +01:00
let new_mrkr = repeat(s:first_char(parent_item.mrkr),
\ s:string_length(parent_item.mrkr)+1)
endif
endif
endif
endif
endif
call s:set_new_mrkr(cur_item, new_mrkr)
call s:adjust_numbered_list(s:get_item(cur_ln), 1, 0)
2014-01-06 13:54:11 +01:00
if cur_ln >= a:to_line | break | endif
2014-01-06 13:30:33 +01:00
let cur_ln = s:get_next_line(cur_ln, 1)
endwhile
call cursor('.', col('$') - cur_col_from_eol)
endfunction "}}}
function! vimwiki#lst#change_marker_in_list(new_mrkr) "{{{
let cur_item = s:get_corresponding_item(line('.'))
let first_item = s:get_first_item_in_list(cur_item, 0)
let last_item = s:get_last_item_in_list(cur_item, 0)
if first_item.type == 0 || last_item.type == 0 | return | endif
let first_item_line = first_item.lnum
let cur_item = first_item
while cur_item.type != 0 && cur_item.lnum <= last_item.lnum
call s:set_new_mrkr(cur_item, a:new_mrkr)
let cur_item = s:get_next_list_item(cur_item, 1)
endwhile
call s:adjust_numbered_list(s:get_item(first_item_line), 0, 0)
endfunction "}}}
2014-01-06 13:54:11 +01:00
2014-01-06 13:30:33 +01:00
"sets kind of the item depending on neighbor items and the parent item
function! s:adjust_mrkr(item) "{{{
if a:item.type == 0 || VimwikiGet('syntax') ==? 'media'
2014-01-06 13:30:33 +01:00
return
endif
let new_mrkr = a:item.mrkr
let neighbor_item = s:get_a_neighbor_item(a:item)
if neighbor_item.type != 0
let new_mrkr = neighbor_item.mrkr
endif
"if possible, set e.g. *** if parent has ** as marker
if neighbor_item.type == 0 && a:item.type == 1 &&
\ index(s:multiple_bullet_chars, s:first_char(a:item.mrkr)) > -1
let parent_item = s:get_parent(a:item)
if parent_item.type == 1 &&
\ s:first_char(parent_item.mrkr) ==# s:first_char(a:item.mrkr)
2014-01-06 13:30:33 +01:00
let new_mrkr = repeat(s:first_char(parent_item.mrkr),
\ s:string_length(parent_item.mrkr)+1)
endif
endif
call s:substitute_string_in_line(a:item.lnum, a:item.mrkr, new_mrkr)
call s:adjust_numbered_list(a:item, 0, 1)
endfunction "}}}
function! s:clone_marker_from_to(from, to) "{{{
let item_from = s:get_item(a:from)
if item_from.type == 0 | return | endif
let new_mrkr = item_from.mrkr . ' '
call s:substitute_rx_in_line(a:to, '^\s*', new_mrkr)
let new_indent = ( VimwikiGet('syntax') !=? 'media' ? indent(a:from) : 0 )
call s:set_indent(a:to, new_indent)
if item_from.cb != ''
call s:create_cb(s:get_item(a:to))
call s:update_state(s:get_parent(s:get_item(a:to)))
endif
if item_from.type == 2
let adjust_from = ( a:from < a:to ? a:from : a:to )
call s:adjust_numbered_list_below(s:get_item(adjust_from), 0)
endif
endfunction "}}}
function! s:remove_mrkr(item) "{{{
let item = a:item
if item.cb != ''
let item = s:remove_cb(item)
let parent_item = s:get_parent(item)
else
let parent_item = s:empty_item()
endif
call s:substitute_rx_in_line(item.lnum, vimwiki#u#escape(item.mrkr).'\s*', '')
call remove(item, 'mrkr')
call remove(item, 'cb')
let item.type = 0
call s:update_state(parent_item)
return item
endfunction "}}}
function! s:create_marker(lnum) "{{{
let new_sibling = s:get_corresponding_item(a:lnum)
if new_sibling.type == 0
let new_sibling = s:get_a_neighbor_item_in_column(a:lnum, virtcol('.'))
endif
if new_sibling.type != 0
call s:clone_marker_from_to(new_sibling.lnum, a:lnum)
else
let cur_item = s:get_item(a:lnum)
call s:set_new_mrkr(cur_item, g:vimwiki_list_markers[0])
call s:adjust_numbered_list(cur_item, 0, 0)
endif
endfunction "}}}
2014-01-06 13:30:33 +01:00
"change markers of list items }}}
"handle keys {{{
function! vimwiki#lst#kbd_o() "{{{
let fold_end = foldclosedend('.')
let lnum = (fold_end == -1) ? line('.') : fold_end
let cur_item = s:get_item(lnum)
"inserting and deleting the x is necessary
"because otherwise the indent is lost
normal! ox
if cur_item.lnum < s:get_last_line_of_item(cur_item)
call s:indent_multiline(cur_item, cur_item.lnum+1)
else
call s:clone_marker_from_to(cur_item.lnum, cur_item.lnum+1)
endif
startinsert!
endfunction "}}}
function! vimwiki#lst#kbd_O() "{{{
normal! Ox
let cur_ln = line('.')
if getline(cur_ln+1) !~# '^\s*$'
2014-01-06 13:30:33 +01:00
call s:clone_marker_from_to(cur_ln+1, cur_ln)
else
call s:clone_marker_from_to(cur_ln-1, cur_ln)
endif
startinsert!
endfunction "}}}
function! s:cr_on_empty_list_item(lnum, behavior) "{{{
if a:behavior == 1
"just make a new list item
normal! gi 
call s:clone_marker_from_to(a:lnum, a:lnum+1)
2014-01-06 13:56:10 +01:00
startinsert!
return
elseif a:behavior == 2
"insert new marker but remove marker in old line
call append(a:lnum-1, '')
startinsert!
return
elseif a:behavior == 3
"list is finished, but cursor stays in current line
let item = s:get_item(a:lnum)
let neighbor_item = s:get_a_neighbor_item(item)
let child_item = s:get_first_child(item)
let parent_item = (item.cb != '') ? s:get_parent(item) : s:empty_item()
normal! "_cc
call s:adjust_numbered_list(neighbor_item, 0, 0)
call s:adjust_numbered_list(child_item, 0, 0)
call s:update_state(parent_item)
startinsert
return
elseif a:behavior == 4
"list is finished, but cursor goes to next line
let item = s:get_item(a:lnum)
let neighbor_item = s:get_a_neighbor_item(item)
let child_item = s:get_first_child(item)
let parent_item = (item.cb != '') ? s:get_parent(item) : s:empty_item()
normal! "_cc
call s:adjust_numbered_list(neighbor_item, 0, 0)
call s:adjust_numbered_list(child_item, 0, 0)
call s:update_state(parent_item)
startinsert
return
elseif a:behavior == 5
"successively decrease level
if s:get_level(a:lnum) > 0
call s:change_level(a:lnum, a:lnum, 'decrease', 0)
startinsert!
else
let item = s:get_item(a:lnum)
let neighbor_item = s:get_a_neighbor_item(item)
let child_item = s:get_first_child(item)
let parent_item = (item.cb != '') ? s:get_parent(item) : s:empty_item()
normal! "_cc
call s:adjust_numbered_list(neighbor_item, 0, 0)
call s:adjust_numbered_list(child_item, 0, 0)
call s:update_state(parent_item)
startinsert
endif
return
endif
endfunction "}}}
function! s:cr_on_empty_line(lnum, behavior) "{{{
"inserting and deleting the x is necessary
"because otherwise the indent is lost
normal! gi x
if a:behavior == 2 || a:behavior == 3
call s:create_marker(a:lnum+1)
endif
endfunction "}}}
function! s:cr_on_list_item(lnum, insert_new_marker, not_at_eol) "{{{
if a:insert_new_marker
"the ultimate feature of this script: make new marker on <CR>
normal! gi 
call s:clone_marker_from_to(a:lnum, a:lnum+1)
"tiny sweet extra feature: indent next line if current line ends with :
if !a:not_at_eol && getline(a:lnum) =~# ':$'
call s:change_level(a:lnum+1, a:lnum+1, 'increase', 0)
endif
else
" || (cur_item.lnum < s:get_last_line_of_item(cur_item))
"indent this line so that it becomes the continuation of the line above
normal! gi 
let prev_line = s:get_corresponding_item(s:get_prev_line(a:lnum+1))
call s:indent_multiline(prev_line, a:lnum+1)
endif
endfunction "}}}
function! vimwiki#lst#kbd_cr(normal, just_mrkr) "{{{
let lnum = line('.')
let has_bp = s:line_has_marker(lnum)
if has_bp != 0 && virtcol('.') < s:text_begin(lnum)
call append(lnum-1, '')
startinsert!
return
endif
if has_bp == 1
call s:cr_on_empty_list_item(lnum, a:just_mrkr)
return
endif
let insert_new_marker = (a:normal == 1 || a:normal == 3)
if getline('.')[col("'^")-1:] =~# '^\s\+$'
let cur_col = 0
else
let cur_col = col("$") - col("'^")
if getline('.')[col("'^")-1] =~# '\s' && exists("*strdisplaywidth")
let ws_behind_cursor =
\ strdisplaywidth(matchstr(getline('.')[col("'^")-1:], '\s\+'),
\ virtcol("'^")-1)
let cur_col -= ws_behind_cursor
endif
if insert_new_marker && cur_col == 0 && getline(lnum) =~# '\s$'
let insert_new_marker = 0
endif
endif
if has_bp == 0
call s:cr_on_empty_line(lnum, a:normal)
endif
if has_bp == 2
call s:cr_on_list_item(lnum, insert_new_marker, cur_col)
endif
call cursor(lnum+1, col("$") - cur_col)
if cur_col == 0
startinsert!
else
startinsert
endif
endfunction "}}}
"creates a list item in the current line or removes it
function! vimwiki#lst#toggle_list_item() "{{{
let cur_col_from_eol = col("$") - col("'^")
let cur_item = s:get_item(line('.'))
if cur_item.type == 0
call s:create_marker(cur_item.lnum)
else
let prev_item = s:get_prev_list_item(cur_item, 1)
if prev_item.type == 0
let prev_item = s:get_corresponding_item(s:get_prev_line(cur_item.lnum))
endif
let cur_item = s:remove_mrkr(cur_item)
let adjust_prev_item = (prev_item.type == 2 &&
\ s:get_level(cur_item.lnum) <= s:get_level(prev_item.lnum)) ? 1 : 0
call s:indent_multiline(prev_item, cur_item.lnum)
if adjust_prev_item
call s:adjust_numbered_list_below(prev_item, 0)
endif
endif
"set cursor position s.t. it's on the same char as before
let new_cur_col = col("$") - cur_col_from_eol
call cursor(cur_item.lnum, new_cur_col >= 1 ? new_cur_col : 1)
if cur_col_from_eol == 0 || getline(cur_item.lnum) =~# '^\s*$'
startinsert!
else
startinsert
endif
endfunction "}}}
2014-01-06 13:30:33 +01:00
"handle keys }}}
2014-01-06 13:30:33 +01:00
"misc stuff {{{
function! vimwiki#lst#setup_marker_infos() "{{{
let s:rx_bullet_chars = '['.join(keys(g:vimwiki_bullet_types), '').']\+'
let s:multiple_bullet_chars = []
for i in keys(g:vimwiki_bullet_types)
if g:vimwiki_bullet_types[i] == 1
call add(s:multiple_bullet_chars, i)
endif
endfor
let s:number_kinds = []
let s:number_divisors = ""
for i in g:vimwiki_number_types
call add(s:number_kinds, i[0])
let s:number_divisors .= vimwiki#u#escape(i[1])
endfor
let s:char_to_rx = {'1': '\d\+', 'i': '[ivxlcdm]\+', 'I': '[IVXLCDM]\+',
\ 'a': '\l\{1,2}', 'A': '\u\{1,2}'}
"create regexp for bulleted list items
let g:vimwiki_rxListBullet = join( map(keys(g:vimwiki_bullet_types),
\'vimwiki#u#escape(v:val).repeat("\\+", g:vimwiki_bullet_types[v:val])'
\ ) , '\|')
"create regex for numbered list items
if !empty(g:vimwiki_number_types)
let g:vimwiki_rxListNumber = '\C\%('
for type in g:vimwiki_number_types[:-2]
let g:vimwiki_rxListNumber .= s:char_to_rx[type[0]] .
\ vimwiki#u#escape(type[1]) . '\|'
endfor
let g:vimwiki_rxListNumber .= s:char_to_rx[g:vimwiki_number_types[-1][0]].
\ vimwiki#u#escape(g:vimwiki_number_types[-1][1]) . '\)'
else
"regex that matches nothing
let g:vimwiki_rxListNumber = '$^'
endif
"the user can set the listsyms as string, but vimwiki needs a list
let g:vimwiki_listsyms_list = split(g:vimwiki_listsyms, '\zs')
endfunction "}}}
function! vimwiki#lst#TO_list_item(inner, visual) "{{{
let lnum = prevnonblank('.')
let item = s:get_corresponding_item(lnum)
if item.type == 0
return
endif
let from_line = item.lnum
if a:inner
let to_line = s:get_last_line_of_item(item)
else
let to_line = s:get_last_line_of_item_incl_children(item)
endif
normal! V
call cursor(to_line, 0)
normal! o
call cursor(from_line, 0)
endfunction "}}}
fun! vimwiki#lst#fold_level(lnum) "{{{
let cur_item = s:get_item(a:lnum)
if cur_item.type != 0
let parent_item = s:get_parent(cur_item)
let child_item = s:get_first_child(cur_item)
let next_item = s:get_next_child_item(parent_item, cur_item)
if child_item.type != 0
return 'a1'
elseif next_item.type == 0
return 's1'
endif
endif
return '='
endf "}}}
2014-01-06 13:30:33 +01:00
"misc stuff }}}