vimwiki

Personal wiki for vim
git clone https://github.com/vimwiki/vimwiki.git
Log | Files | Refs | README | LICENSE

commit 3eaaf12b2dd456ba66b254a6a80b478c9f2e454f
parent 8a46108ef6eafe4da3ca9adf4b0caf0b46d97497
Author: Maxim Kim <habamax@gmail.com>
Date:   Sun,  8 Sep 2013 14:53:42 +0400

Merge branch 'new-lists' of github.com:vimwiki/vimwiki into new-lists

Diffstat:
Mautoload/vimwiki/base.vim | 3+--
Mautoload/vimwiki/lst.vim | 1587++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Mautoload/vimwiki/tbl.vim | 9+++++++--
Mautoload/vimwiki/u.vim | 13+++++++++++++
Mdoc/vimwiki.txt | 273+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Mftplugin/vimwiki.vim | 250+++++++++++++++++++++++++++----------------------------------------------------
Mplugin/vimwiki.vim | 2+-
Msyntax/vimwiki.vim | 58++++++++++++++++++++--------------------------------------
Msyntax/vimwiki_default.vim | 16++++++++++++----
Msyntax/vimwiki_markdown.vim | 13+++++++++----
Msyntax/vimwiki_markdown_custom.vim | 14++++++--------
Msyntax/vimwiki_media.vim | 14+++++++++-----
12 files changed, 1552 insertions(+), 700 deletions(-)

diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim @@ -1424,8 +1424,7 @@ endfunction " }}} " arguments rxUrl, rxDesc, and rxStyle are copied verbatim, without any " special character escapes or substitutions. function! vimwiki#base#apply_template(template, rxUrl, rxDesc, rxStyle) "{{{ - let magic_chars = '.*[\^$' - let lnk = escape(a:template, magic_chars) + let lnk = vimwiki#u#escape(a:template) if a:rxUrl != "" let lnk = substitute(lnk, '__LinkUrl__', '\='."'".a:rxUrl."'", '') endif diff --git a/autoload/vimwiki/lst.vim b/autoload/vimwiki/lst.vim @@ -1,555 +1,1382 @@ " vim:tabstop=2:shiftwidth=2:expandtab:foldmethod=marker:textwidth=79 " Vimwiki autoload plugin file -" Todo lists related stuff here. -" Author: Maxim Kim <habamax@gmail.com> +" Everything concerning bulleted and numbered lists and checkboxes +" Author: Daniel Schemala <istjanichtzufassen@gmail.com> " Home: http://code.google.com/p/vimwiki/ if exists("g:loaded_vimwiki_list_auto") || &cp finish endif -let g:loaded_vimwiki_lst_auto = 1 +let g:loaded_vimwiki_list_auto = 1 -" Script variables {{{ -let s:rx_li_box = '\[.\?\]' -" }}} +" incrementation functions for the various kinds of numbers {{{ -" Script functions {{{ +function! s:increment_1(value) "{{{ + return eval(a:value) + 1 +endfunction "}}} -" Get unicode string symbol at index -function! s:str_idx(str, idx) "{{{ - " Unfortunatly vimscript cannot get symbol at index in unicode string such as - " '✗○◐●✓' - return matchstr(a:str, '\%'.a:idx.'v.') +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 "}}} -" Get checkbox regexp -function! s:rx_li_symbol(rate) "{{{ - let result = '' - if a:rate == 100 - let result = s:str_idx(g:vimwiki_listsyms, 5) - elseif a:rate == 0 - let result = s:str_idx(g:vimwiki_listsyms, 1) - elseif a:rate >= 67 - let result = s:str_idx(g:vimwiki_listsyms, 4) - elseif a:rate >= 34 - let result = s:str_idx(g:vimwiki_listsyms, 3) - else - let result = s:str_idx(g:vimwiki_listsyms, 2) +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 "}}} - return '\['.result.'\]' +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 "}}} -" Get blank checkbox -function! s:blank_checkbox() "{{{ - return '['.s:str_idx(g:vimwiki_listsyms, 1).'] ' +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 "}}} -" Get regexp of the list item. -function! s:rx_list_item() "{{{ - return '\('.g:vimwiki_rxListBullet.'\|'.g:vimwiki_rxListNumber.'\)' +" incrementation functions for the various kinds of numbers }}} + +function! s:substitute_rx_in_line(lnum, pattern, new_string) "{{{ + call setline(a:lnum, substitute(getline(a:lnum), a:pattern, a:new_string, '')) endfunction "}}} -" Get regexp of the list item with checkbox. -function! s:rx_cb_list_item() "{{{ - return s:rx_list_item().'\s*\zs\[.\?\]' +function! s:substitute_string_in_line(lnum, pattern, new_string) "{{{ + call s:substitute_rx_in_line(a:lnum, vimwiki#u#escape(a:pattern), a:new_string) endfunction "}}} -" Get level of the list item. -function! s:get_level(lnum) "{{{ - if VimwikiGet('syntax') == 'media' - let level = vimwiki#u#count_first_sym(getline(a:lnum)) +"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 "}}} + +"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 "}}} -" Get previous list item. -" Returns: line number or 0. -function! s:prev_list_item(lnum) "{{{ - let c_lnum = a:lnum - 1 - while c_lnum >= 1 - let line = getline(c_lnum) - if line =~ s:rx_list_item() - return c_lnum - endif - if line =~ '^\s*$' - return 0 +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 "}}} + +function! s:empty_item() "{{{ + return {'type': 0} +endfunction "}}} + +"Returns: the list item after a:item in its list or empty item +"If a:all is 1, the markers can differ +function! s:get_next_list_item(item, all) "{{{ + return s:get_next_or_prev_list_item(a:item, +1, line('$')+1, a:all) +endfunction "}}} + +"Returns: the list item before a:item in its list or empty item +"If a:all is 1, the markers can differ +function! s:get_prev_list_item(item, all) "{{{ + return s:get_next_or_prev_list_item(a:item, -1, 0, a:all) +endfunction "}}} + +function! s:get_next_or_prev_list_item(item, direction, until, all) "{{{ + let org_lvl = s:get_level(a:item.lnum) + if !a:all + let org_regex = s:regexp_of_marker(a:item) + endif + let cur_ln = s:get_next_prev_line(a:item.lnum, a:direction) + while cur_ln != a:until + let cur_lvl = s:get_level(cur_ln) + let cur_linecontent = getline(cur_ln) + + if cur_lvl == org_lvl + if a:all || cur_linecontent =~# '^\s*'.org_regex.'\s' + return s:get_item(cur_ln) + else + return s:empty_item() + endif + elseif cur_lvl < org_lvl + return s:empty_item() + else + let cur_ln = s:get_next_prev_line(cur_ln, a:direction) endif - let c_lnum -= 1 endwhile - return 0 + return s:empty_item() endfunction "}}} -" Get next list item in the list. -" Returns: line number or 0. -function! s:next_list_item(lnum) "{{{ - let c_lnum = a:lnum + 1 - while c_lnum <= line('$') - let line = getline(c_lnum) - if line =~ s:rx_list_item() - return c_lnum +function! s:first_char(string) "{{{ + return matchstr(a:string, '^.') +endfunction "}}} + +"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\+' + 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 - if line =~ '^\s*$' - return 0 + 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:get_first_item_in_list(item, all) "{{{ + let cur_item = a:item + while 1 + let prev_item = s:get_prev_list_item(cur_item, a:all) + if prev_item.type == 0 + break + else + let cur_item = prev_item endif - let c_lnum += 1 endwhile - return 0 + return cur_item endfunction "}}} -" Find next list item in the buffer. -" Returns: line number or 0. -function! s:find_next_list_item(lnum) "{{{ - let c_lnum = a:lnum + 1 - while c_lnum <= line('$') - let line = getline(c_lnum) - if line =~ s:rx_list_item() - return c_lnum +function! s:get_last_item_in_list(item, all) "{{{ + let cur_item = a:item + while 1 + let next_item = s:get_next_list_item(cur_item, a:all) + if next_item.type == 0 + break + else + let cur_item = next_item endif - let c_lnum += 1 endwhile - return 0 -endfunction "}}} - -" Set state of the list item on line number "lnum" to [ ] or [x] -function! s:set_state(lnum, rate) "{{{ - let line = getline(a:lnum) - let state = s:rx_li_symbol(a:rate) - let line = substitute(line, s:rx_li_box, state, '') - call setline(a:lnum, line) -endfunction "}}} - -" Get state of the list item on line number "lnum" -function! s:get_state(lnum) "{{{ - let state = 0 - let line = getline(a:lnum) - let opt = matchstr(line, s:rx_cb_list_item()) - if opt =~ s:rx_li_symbol(100) - let state = 100 - elseif opt =~ s:rx_li_symbol(0) - let state = 0 - elseif opt =~ s:rx_li_symbol(25) - let state = 25 - elseif opt =~ s:rx_li_symbol(50) - let state = 50 - elseif opt =~ s:rx_li_symbol(75) - let state = 75 + 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, ...) "{{{ + if getline(a:lnum) =~# '^\s*'.g:vimwiki_rxPreStart + let cur_ln = a:lnum + 1 + while cur_ln <= line('$') && getline(cur_ln) !~# '^\s*'.g:vimwiki_rxPreEnd.'\s*$' + let cur_ln += 1 + endwhile + let next_line = nextnonblank(cur_ln+1) + else + let next_line = nextnonblank(a:lnum+1) endif - return state + + 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 1 if there is checkbox on a list item, 0 otherwise. -function! s:is_cb_list_item(lnum) "{{{ - return getline(a:lnum) =~ s:rx_cb_list_item() +"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) + + if getline(prev_line) =~# '^\s*'.g:vimwiki_rxPreEnd.'\s*$' + let cur_ln = a:lnum - 1 + while 1 + if cur_ln == 0 || getline(cur_ln) =~# '^\s*'.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 "}}} -" Returns start line number of list item, 0 if it is not a list. -function! s:is_list_item(lnum) "{{{ - let c_lnum = a:lnum - while c_lnum >= 1 - let line = getline(c_lnum) - if line =~ s:rx_list_item() - return c_lnum - endif - if line =~ '^\s*$' - return 0 +function! s:get_next_prev_line(lnum, dir) "{{{ + if a:dir == 1 + return s:get_next_line(a:lnum) + else + return s:get_prev_line(a:lnum) + endif +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 indent(c_lnum) > indent(a:lnum) - return 0 + if cur_item.lnum > line('$') || cur_item.lnum <= 0 || s:get_level(cur_item.lnum) <= org_lvl + return s:empty_item() endif - let c_lnum -= 1 + let cur_item = s:get_item(s:get_next_line(cur_item.lnum)) endwhile - return 0 endfunction "}}} -" Returns char column of checkbox. Used in parent/child checks. -function! s:get_li_pos(lnum) "{{{ - return stridx(getline(a:lnum), '[') + +"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 "}}} -" Returns list of line numbers of parent and all its child items. -function! s:get_child_items(lnum) "{{{ - let result = [] - let lnum = a:lnum - let p_pos = s:get_level(lnum) +"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) - " add parent - call add(result, lnum) + let cur_item = a:item + while 1 + if a:recursive + call s:adjust_items_recursively(cur_item) + endif - let lnum = s:next_list_item(lnum) - while lnum != 0 && s:is_list_item(lnum) && s:get_level(lnum) > p_pos - call add(result, lnum) - let lnum = s:next_list_item(lnum) + 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 result + return cur_item endfunction "}}} -" Returns list of line numbers of all items of the same level. -function! s:get_sibling_items(lnum) "{{{ - let result = [] - let lnum = a:lnum - let ind = s:get_level(lnum) +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) - while lnum != 0 && s:get_level(lnum) >= ind - if s:get_level(lnum) == ind && s:is_cb_list_item(lnum) - call add(result, lnum) + let child_item = s:get_next_child_item(a:parent, last_item) + if child_item.type == 0 + return last_item endif - let lnum = s:next_list_item(lnum) endwhile +endfunction "}}} + +"Renumbers the list a:item is in. +"If a:all == 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, all, recursive) "{{{ + if !(a:item.type == 2 || (a:item.type == 1 && (a:all || a:recursive))) + return s:empty_item() + end + + let first_item = s:get_first_item_in_list(a:item, a:all) + + 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 lnum = s:prev_list_item(a:lnum) - while lnum != 0 && s:get_level(lnum) >= ind - if s:get_level(lnum) == ind && s:is_cb_list_item(lnum) - call add(result, lnum) + 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:all == 0 || next_first_item.type == 0 + return last_item endif - let lnum = s:prev_list_item(lnum) + let first_item = next_first_item endwhile - - return result endfunction "}}} -" Returns line number of the parent of lnum item -function! s:get_parent_item(lnum) "{{{ - let lnum = a:lnum - let ind = s:get_level(lnum) +"Returns: the (rounded) rate of [X] checked child items 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, 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 lnum = s:prev_list_item(lnum) - while lnum != 0 && s:is_list_item(lnum) && s:get_level(lnum) >= ind - let lnum = s:prev_list_item(lnum) + 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 "}}} - if s:is_cb_list_item(lnum) - return lnum +function! s:rate_to_state(rate) "{{{ + let state = '' + if a:rate == 100 + let state = g:vimwiki_listsyms[4] + elseif a:rate == 0 + let state = g:vimwiki_listsyms[0] + elseif a:rate >= 67 + let state = g:vimwiki_listsyms[3] + elseif a:rate >= 34 + let state = g:vimwiki_listsyms[2] else - return a:lnum + let state = g:vimwiki_listsyms[1] endif + return state endfunction "}}} -" Creates checkbox in a list item. -function! s:create_cb_list_item(lnum) "{{{ - let line = getline(a:lnum) - let m = matchstr(line, s:rx_list_item()) - if m != '' - let li_content = substitute(strpart(line, len(m)), '^\s*', '', '') - let line = substitute(m, '\s*$', ' ', '').s:blank_checkbox().li_content - call setline(a:lnum, line) +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 -endfunction "}}} -" Tells if all of the sibling list items are checked or not. -function! s:all_siblings_checked(lnum) "{{{ - let result = 0 - let cnt = 0 - let siblings = s:get_sibling_items(a:lnum) - for lnum in siblings - let cnt += s:get_state(lnum) - endfor - let result = cnt/len(siblings) - return result + 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 "}}} -" Creates checkbox on a list item if there is no one. -function! s:TLI_create_checkbox(lnum) "{{{ - if a:lnum && !s:is_cb_list_item(a:lnum) - if g:vimwiki_auto_checkbox - call s:create_cb_list_item(a:lnum) +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 + + "set state and set the parents states recursively + let state_changed = s:set_state(a:item, new_rate) + if state_changed + call s:update_state(s:get_parent(a:item)) endif - return 1 endif - return 0 endfunction "}}} -" Switch state of the child list items. -function! s:TLI_switch_child_state(lnum) "{{{ - let current_state = s:get_state(a:lnum) - if current_state == 100 - let new_state = 0 - else - let new_state = 100 +"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 - for lnum in s:get_child_items(a:lnum) - call s:set_state(lnum, new_state) - endfor + + let new_item = a:item + let new_item.cb = g:vimwiki_listsyms[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 "}}} -" Switch state of the parent list items. -function! s:TLI_switch_parent_state(lnum) "{{{ - let c_lnum = a:lnum - while s:is_cb_list_item(c_lnum) - let parent_lnum = s:get_parent_item(c_lnum) - if parent_lnum == c_lnum - break +"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 - call s:set_state(parent_lnum, s:all_siblings_checked(c_lnum)) + 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 "}}} - let c_lnum = parent_lnum +"Returns: the last line of a (possibly multiline) item +"Note: there can be other list items inbetween these lines +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 "}}} -function! s:TLI_toggle(lnum) "{{{ - if !s:TLI_create_checkbox(a:lnum) - call s:TLI_switch_child_state(a:lnum) +"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 "}}} + +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 "}}} + +"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 - call s:TLI_switch_parent_state(a:lnum) endfunction "}}} -" Script functions }}} +"Renumbers the list the cursor is in +"also update its parents 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 "}}} -" Toggle list item between [ ] and [X] -function! vimwiki#lst#ToggleListItem(line1, line2) "{{{ - let line1 = a:line1 - let line2 = a:line2 +"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 "}}} - if line1 != line2 && !s:is_list_item(line1) - let line1 = s:find_next_list_item(line1) +"Toggle checkbox between [ ] and [X] or creates one +function! vimwiki#lst#toggle_cb(line1, line2) "{{{ + let from_item = s:get_corresponding_item(a:line1) + let to_item = s:get_corresponding_item(a:line2) + if from_item.type == 0 + return endif - let c_lnum = line1 - while c_lnum != 0 && c_lnum <= line2 - let li_lnum = s:is_list_item(c_lnum) + let parent_items_of_lines = [] - if li_lnum - let li_level = s:get_level(li_lnum) - if c_lnum == line1 - let start_li_level = li_level + if from_item.cb == '' + + "if line1 has no CB, make a CB in every selected line + let parent_items_of_lines = [] + for cur_ln in range(from_item.lnum, to_item.lnum) + 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 - if li_level <= start_li_level - call s:TLI_toggle(li_lnum) - let start_li_level = li_level + "if line1 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 + + for cur_ln in range(from_item.lnum, to_item.lnum) + 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! 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 "}}} + +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 "}}} + +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' + 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 "}}} + +function! vimwiki#lst#change_marker(line1, line2, new_mrkr) "{{{ + let cur_col_from_eol = col("$") - col("'^") + let new_mrkr = a:new_mrkr + let cur_ln = a:line1 + 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) + 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) + 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) + let new_mrkr = repeat(s:first_char(parent_item.mrkr), s:string_length(parent_item.mrkr)+1) + endif + endif + endif + endif + endif - let c_lnum = s:find_next_list_item(c_lnum) + call s:set_new_mrkr(cur_item, new_mrkr) + call s:adjust_numbered_list(s:get_item(cur_ln), 1, 0) + + if cur_ln >= a:line2 | break | endif + let cur_ln = s:get_next_line(cur_ln, 1) endwhile + call cursor('.', col('$') - cur_col_from_eol) endfunction "}}} -function! vimwiki#lst#kbd_cr() "{{{ - " This function is heavily relies on proper 'set comments' option. - let cr = "\<CR>" - if getline('.') =~ s:rx_cb_list_item() - let cr .= s:blank_checkbox() +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 cr + return item endfunction "}}} -function! vimwiki#lst#kbd_oO(cmd) "{{{ - " cmd should be 'o' or 'O' +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) - let l:count = v:count1 - while l:count > 0 + if first_item.type == 0 || last_item.type == 0 + return + endif - let beg_lnum = foldclosed('.') - let end_lnum = foldclosedend('.') - if end_lnum != -1 && a:cmd ==# 'o' - let lnum = end_lnum - let line = getline(beg_lnum) - else - let line = getline('.') - let lnum = line('.') + 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 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 "}}} - let m = matchstr(line, s:rx_list_item()) - let res = '' - if line =~ s:rx_cb_list_item() - let res = substitute(m, '\s*$', ' ', '').s:blank_checkbox() - elseif line =~ s:rx_list_item() - let res = substitute(m, '\s*$', ' ', '') - elseif &autoindent || &smartindent - let res = matchstr(line, '^\s*') - endif +function! vimwiki#lst#remove_cb_in_list() "{{{ + let first_item = s:get_first_item_in_list(s:get_corresponding_item(line('.')), 0) - if a:cmd ==# 'o' - call append(lnum, res) - call cursor(lnum + 1, col('$')) + 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 else - call append(lnum - 1, res) - call cursor(lnum, col('$')) + let cur_item = next_item endif + endwhile - let l:count -= 1 + call s:update_state(s:get_parent(first_item)) +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 - startinsert! + call s:adjust_numbered_list(s:get_item(first_item_line), 0, 0) +endfunction "}}} +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! vimwiki#lst#default_symbol() "{{{ - " TODO: initialize default symbol from syntax/vimwiki_xxx.vim - if VimwikiGet('syntax') == 'default' - return '-' +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 - return '*' + let old_indent = indent(a:item.lnum) + if &shiftround + let new_indent = (old_indent - 1) / &shiftwidth * &shiftwidth + else + let new_indent = old_indent - &shiftwidth + endif + call s:set_indent(a:item.lnum, new_indent) + let removed_indent = new_indent - old_indent endif + return removed_indent endfunction "}}} -function vimwiki#lst#get_list_margin() "{{{ - if VimwikiGet('list_margin') < 0 - return &sw +function! s:increase_level(item) "{{{ + let additional_space = 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 - return VimwikiGet('list_margin') + let old_indent = indent(a:item.lnum) + if &shiftround + let new_indent = (old_indent / &shiftwidth + 1) * &shiftwidth + else + let new_indent = old_indent + &shiftwidth + endif + call s:set_indent(a:item.lnum, new_indent) + let additional_indent = new_indent - old_indent endif + return additional_indent endfunction "}}} -function s:get_list_sw() "{{{ - if VimwikiGet('syntax') == 'media' - return 1 +"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 && + \ 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 - return &sw + call s:set_indent(a:lnum, indent(a:lnum) + a:indent_by) + endif +endfunction "}}} + +"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 "}}} + +"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' + 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 -endfunction "}}} -function s:get_list_nesting_level(lnum) "{{{ - if VimwikiGet('syntax') == 'media' - if getline(a:lnum) !~ s:rx_list_item() - let level = 0 - else - let level = vimwiki#u#count_first_sym(getline(a:lnum)) - 1 - let level = level < 0 ? 0 : level + "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) + 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 "}}} + +"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 + execute a:from_line.','.a:to_line. (a:direction == 'increase' ? '>' : '<') + 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 level = indent(a:lnum) + let to_line = a:to_line endif - return level -endfunction "}}} -function s:get_list_indent(lnum) "{{{ - if VimwikiGet('syntax') == 'media' - return indent(a:lnum) + if from_item.type == 0 || 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 + + 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 - return 0 + call s:adjust_numbered_list(from_item, 0, 0) + call s:adjust_numbered_list(to_be_adjusted, 0, 0) endif -endfunction "}}} +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 "}}} -function! s:compose_list_item(n_indent, n_nesting, sym_nest, sym_bullet, li_content, ...) "{{{ - if a:0 - let sep = a:1 +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 "}}} + +"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 "}}} + +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 - let sep = '' + call s:clone_marker_from_to(cur_item.lnum, cur_item.lnum+1) endif - let li_indent = repeat(' ', max([0,a:n_indent])).sep - let li_nesting = repeat(a:sym_nest, max([0,a:n_nesting])).sep - if len(a:sym_bullet) > 0 - let li_bullet = a:sym_bullet.' '.sep + startinsert! +endfunction "}}} + +function! vimwiki#lst#kbd_O() "{{{ + normal! Ox + let cur_ln = line('.') + if getline(cur_ln+1) !~ '^\s*$' + call s:clone_marker_from_to(cur_ln+1, cur_ln) else - let li_bullet = ''.sep + call s:clone_marker_from_to(cur_ln-1, cur_ln) endif - return li_indent.li_nesting.li_bullet.a:li_content + startinsert! endfunction "}}} -function s:compose_cb_bullet(prev_cb_bullet, sym) "{{{ - return a:sym.matchstr(a:prev_cb_bullet, '\S*\zs\s\+.*') +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! vimwiki#lst#change_level(...) "{{{ - let default_sym = vimwiki#lst#default_symbol() - let cmd = '>>' - let sym = default_sym +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(s:get_item(a:lnum)) + 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 "}}} - " parse argument - if a:0 - if a:1 != '<<' && a:1 != '>>' - let cmd = '--' - let sym = a:1 +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) + 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 cmd = a:1 + 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 - endif - " is symbol valid - if sym.' ' !~ s:rx_cb_list_item() && sym.' ' !~ s:rx_list_item() return endif +endfunction "}}} + +function! s:cr_on_empty_line(lnum, behavior) "{{{ + if a:behavior == 2 || a:behavior == 3 + normal! gi + call s:create_marker(a:lnum+1) + elseif a:behavior == 1 || a:behavior == 4 + normal! gix + endif +endfunction "}}} + +function! s:cr_on_list_item(lnum, insert_new_marker) "{{{ + 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 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 "}}} - " parsing setup +function! vimwiki#lst#kbd_cr(normal, just_mrkr) "{{{ let lnum = line('.') - let line = getline('.') + let has_bp = s:line_has_marker(lnum) - let list_margin = vimwiki#lst#get_list_margin() - let list_sw = s:get_list_sw() - let n_nesting = s:get_list_nesting_level(lnum) - let n_indent = s:get_list_indent(lnum) + if has_bp != 0 && virtcol('.') < s:text_begin(lnum) + call append(lnum-1, '') + startinsert! + return + endif - " remove indent and nesting - let li_bullet_and_content = strpart(line, n_nesting + n_indent) + if has_bp == 1 + call s:cr_on_empty_list_item(lnum, a:just_mrkr) + return + endif - " list bullet and checkbox - let cb_bullet = matchstr(li_bullet_and_content, s:rx_list_item()). - \ matchstr(li_bullet_and_content, s:rx_cb_list_item()) + 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 insert_new_marker && cur_col == 0 && getline(lnum) =~ '\s$' + let insert_new_marker = 0 + endif + endif - " XXX: it could be not unicode proof --> if checkboxes are set up with unicode syms - " content - let li_content = strpart(li_bullet_and_content, len(cb_bullet)) + if has_bp == 0 + call s:cr_on_empty_line(lnum, a:normal) + endif - " trim - let cb_bullet = vimwiki#u#trim(cb_bullet) - let li_content = vimwiki#u#trim(li_content) + if has_bp == 2 + call s:cr_on_list_item(lnum, insert_new_marker) + endif - " nesting symbol - if VimwikiGet('syntax') == 'media' - if len(cb_bullet) > 0 - let sym_nest = cb_bullet[0] - else - let sym_nest = sym - endif + call cursor(lnum+1, col("$") - cur_col) + if cur_col == 0 + startinsert! else - let sym_nest = ' ' + startinsert endif - if g:vimwiki_debug - echomsg "PARSE: Sw [".list_sw."]" - echomsg s:compose_list_item(n_indent, n_nesting, sym_nest, cb_bullet, li_content, '|') - 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('.')) - " change level - if cmd == '--' - let cb_bullet = s:compose_cb_bullet(cb_bullet, sym) - if VimwikiGet('syntax') == 'media' - let sym_nest = sym + 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 - elseif cmd == '>>' - if cb_bullet == '' - let cb_bullet = sym - else - let n_nesting = n_nesting + list_sw - endif - elseif cmd == '<<' - let n_nesting = n_nesting - list_sw - if VimwikiGet('syntax') == 'media' - if n_nesting < 0 - let cb_bullet = '' - endif - else - if n_nesting < list_margin - let cb_bullet = '' - 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 - let n_nesting = max([0, n_nesting]) + "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 g:vimwiki_debug - echomsg "SHIFT:" - echomsg s:compose_list_item(n_indent, n_nesting, sym_nest, cb_bullet, li_content, '|') + if cur_col_from_eol == 0 || getline(cur_item.lnum) =~ '^\s*$' + startinsert! + else + startinsert endif +endfunction "}}} - " XXX: this is the code that adds the initial indent - let add_nesting = VimwikiGet('syntax') != 'media' - if n_indent + n_nesting*(add_nesting) < list_margin - let n_indent = list_margin - n_nesting*(add_nesting) - endif +function! vimwiki#lst#default_symbol() "{{{ + return g:vimwiki_list_markers[0] +endfunction "}}} - if g:vimwiki_debug - echomsg "INDENT:" - echomsg s:compose_list_item(n_indent, n_nesting, sym_nest, cb_bullet, li_content, '|') +function! vimwiki#lst#get_list_margin() "{{{ + if VimwikiGet('list_margin') < 0 + return &sw + else + return VimwikiGet('list_margin') endif +endfunction "}}} + +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 line = s:compose_list_item(n_indent, n_nesting, sym_nest, cb_bullet, li_content) + 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 - " replace - call setline(lnum, line) - call cursor(lnum, match(line, '\S') + 1) 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 "}}} diff --git a/autoload/vimwiki/tbl.vim b/autoload/vimwiki/tbl.vim @@ -447,7 +447,7 @@ endfunction "}}} function! vimwiki#tbl#kbd_cr() "{{{ let lnum = line('.') if !s:is_table(getline(lnum)) - return "\<CR>" + return "" endif if s:is_separator(getline(lnum+1)) || !s:is_table(getline(lnum+1)) @@ -507,9 +507,14 @@ function! vimwiki#tbl#format(lnum, ...) "{{{ endif let indent = s:get_indent(a:lnum) + if &expandtab + let indentstring = repeat(' ', indent) + else + let indentstring = repeat(' ', indent / &tabstop) . repeat(' ', indent % &tabstop) + endif for [lnum, row] in s:get_aligned_rows(a:lnum, col1, col2) - let row = repeat(' ', indent).row + let row = indentstring.row call setline(lnum, row) endfor diff --git a/autoload/vimwiki/u.vim b/autoload/vimwiki/u.vim @@ -75,3 +75,16 @@ function! vimwiki#u#path_common_pfx(path1, path2) "{{{ endif endfunction "}}} +function! vimwiki#u#escape(string) "{{{ + return escape(a:string, '.*[]\^$') +endfunction "}}} + +" Load concrete Wiki syntax: sets regexes and templates for headers and links +function vimwiki#u#reload_regexes() "{{{ + execute 'runtime! syntax/vimwiki_'.VimwikiGet('syntax').'.vim' +endfunction "}}} + +" Load syntax-specific functionality +function vimwiki#u#reload_regexes_custom() "{{{ + execute 'runtime! syntax/vimwiki_'.VimwikiGet('syntax').'_custom.vim' +endfunction "}}} diff --git a/doc/vimwiki.txt b/doc/vimwiki.txt @@ -280,13 +280,6 @@ NORMAL MODE *vimwiki-local-mappings* To remap: > :nmap <Leader>rr <Plug>VimwikiRenameLink < - *vimwiki_<C-Space>* -<C-Space> Toggle list item on/off (checked/unchecked) - Maps to |:VimwikiToggleListItem|. - To remap: > - :nmap <leader>tt <Plug>VimwikiToggleListItem -< See |vimwiki-todo-lists|. - *vimwiki_=* = Add header level. Create if needed. There is nothing to indent with '==' command in @@ -308,27 +301,80 @@ NORMAL MODE *vimwiki-local-mappings* the cursor over a word or link, or in visual mode with the selected text . - *vimwiki_glm* -glm Increase the indent of a single-line list item. - - *vimwiki_gll* -gll Decrease the indent of a single-line list item. - - *vimwiki_glstar* *vimwiki_gl8* -gl* or gl8 Switch or insert a "*" symbol. Only available in - supported syntaxes. - - *vimwiki_gl#* *vimwiki_gl3* -gl# or gl3 Switch or insert a "#" symbol. Only available in - supported syntaxes. - - *vimwiki_gl-* -gl- Switch or insert a "-" symbol. Only available in - supported syntaxes. + *vimwiki_<C-Space>* +<C-Space> Toggle list item on/off (checked/unchecked) + Maps to |:VimwikiToggleListItem|. + To remap: > + :nmap <leader>tt <Plug>VimwikiToggleListItem +< See |vimwiki-todo-lists|. - *vimwiki_gl1* -gl1 Switch or insert a "1." symbol. Only available in - supported syntaxes. + *vimwiki_gl<Space>* +gl<Space> Remove checkbox from list item. + + *vimwiki_gL<Space>* +gL<Space> Remove checkboxes from all sibling list items. + + *vimwiki_gll* *vimwiki_gLl* +gll Increase the level of a list item. +gLl Increase the level of a list item and all child items. + + *vimwiki_glh* *vimwiki_gLh* +glh Decrease the level of a list item. +gLh Decrease the level of a list item and all child items. + + *vimwiki_glr* *vimwiki_gLr* +glr Renumber list items for the current list. +gLr Renumber list items for the whole buffer. + + *vimwiki_glstar* *vimwiki_gLstar* +gl* Make a list item out of normal line or change the marker + of the current item to *. +gL* Change the marker of the current list to *. + + *vimwiki_gl#* *vimwiki_gL#* +gl# Make a list item out of normal line or change the marker + of the current item to #. +gL# Change the marker of the current list to #. + + *vimwiki_gl-* *vimwiki_gL-* +gl- Make a list item out of normal line or change the marker + of the current item to -. +gL- Change the marker of the current list to -. + + *vimwiki_gl.* *vimwiki_gL.* +gl. Make a list item out of normal line or change the marker + of the current item to •. +gL. Change the marker of the current list to •. + + *vimwiki_gl1* *vimwiki_gL1* +gl1 Make a list item out of normal line or change the marker + of the current item to 1., the numbering is adjusted + according to the surrounding list items. +gL1 Change the marker of the current list to 1. 2. 3. ... + + *vimwiki_gla* *vimwiki_gLa* +gla Make a list item out of normal line or change the marker + of the current item to a), the numbering is adjusted + according to the surrounding list items. +gLa Change the marker of the current list to a) b) c) ... + + *vimwiki_glA* *vimwiki_gLA* +glA Make a list item out of normal line or change the marker + of the current item to A), the numbering is adjusted + according to the surrounding list items. +gLA Change the marker of the current list to A) B) C) ... + + *vimwiki_gli* *vimwiki_gLi* +gli Make a list item out of normal line or change the marker + of the current item to i), the numbering is adjusted + according to the surrounding list items. +gLi Change the marker of the current list to i) ii) iii) ... + + *vimwiki_glI* *vimwiki_gLI* +glI Make a list item out of normal line or change the marker + of the current item to I), the numbering is adjusted + according to the surrounding list items. +gLI Change the marker of the current list to I) II) III) ... *vimwiki_gqq* *vimwiki_gww* gqq Format table. If you made some changes to a table @@ -372,15 +418,43 @@ Note: <2-LeftMouse> is just left double click. INSERT MODE *vimwiki-table-mappings* - *vimwiki_i_<CR>* + *vimwiki_i_<CR>_table* <CR> Go to the table cell beneath the current one, create a new row if on the last one. - - *vimwiki_i_<Tab>* + + *vimwiki_i_<Tab>_table* <Tab> Go to the next table cell, create a new row if on the last cell. See |g:vimwiki_table_mappings| to turn them off. +INSERT MODE *vimwiki-list-mappings* + *vimwiki_i_<CR>_list* +<CR> In a list item, insert a new bullet or number in the + next line, numbers are incremented. + In an empty list item, delete the item marker. This is + useful to end a list, you simply press <CR> twice. + + *vimwiki_i_<S-CR>_list* +<S-CR> Does not insert a new list item, useful to create + multilined list items. + + *vimwiki_i_<C-T>_list* +<C-T> Increase the level of a list item. + + *vimwiki_i_<C-D>_list* +<C-D> Decrease the level of a list item. + + *vimwiki_i_<C-L>_<C-J>_list* +<C-L><C-J> Change the marker of the current list item to the next + available. From - to • to 1. to * to I) to a). + + *vimwiki_i_<C-L>_<C-K>_list* +<C-L><C-K> Change the marker of the current list item to the prev + available. From - to a) to I) to * to 1. to •. + + *vimwiki_i_<C-L>_<C-M>_list* +<C-L><C-M> Create/remove a marker from a list item. + ------------------------------------------------------------------------------ 3.3. Text objects *vimwiki-text-objects* @@ -688,72 +762,79 @@ two lines. 5.5. Lists *vimwiki-syntax-lists* Unordered lists: > + - Bulleted list item 1 + - Bulleted list item 2 +or: > + • Bulleted list item 1 + • Bulleted list item 2 +or: > * Bulleted list item 1 * Bulleted list item 2 - * Bulleted list sub item 1 - * Bulleted list sub item 2 - * more ... - * and more ... - * ... - * Bulleted list sub item 3 - * etc. or: > - - Bulleted list item 1 - - Bulleted list item 2 - - Bulleted list sub item 1 - - Bulleted list sub item 2 - - more ... - - and more ... - - ... - - Bulleted list sub item 3 - - etc. + # Bulleted list item 1 + # Bulleted list item 2 -or mix: > - - Bulleted list item 1 - - Bulleted list item 2 - * Bulleted list sub item 1 - * Bulleted list sub item 2 - * more ... - - and more ... - - ... - * Bulleted list sub item 3 - * etc. Ordered lists: > - # Numbered list item 1 - # Numbered list item 2 - # Numbered list sub item 1 - # Numbered list sub item 2 - # more ... - # and more ... - # ... - # Numbered list sub item 3 - # etc. - -It is possible to mix bulleted and numbered lists: > - * Bulleted list item 1 - * Bulleted list item 2 - # Numbered list sub item 1 - # Numbered list sub item 2 + 1. Numbered list item 1 + 2. Numbered list item 2 + 3. Numbered list item 3 +or: > + 1) Numbered list item 1 + 2) Numbered list item 2 + 3) Numbered list item 3 +or: > + a) Numbered list item 1 + b) Numbered list item 2 + c) Numbered list item 3 +or: > + A) Numbered list item 1 + B) Numbered list item 2 + C) Numbered list item 3 +or: > + i) Numbered list item 1 + ii) Numbered list item 2 + iii) Numbered list item 3 +or: > + I) Numbered list item 1 + II) Numbered list item 2 + III) Numbered list item 3 -Note that a space after *, - or # is essential. +You can nest and mix the various types: > + - Bulleted list item 1 + - Bulleted list item 2 + a) Numbered list sub item 1 + b) more ... + • and more ... + • ... + c) Numbered list sub item 3 + 1. Numbered list sub sub item 1 + 2. Numbered list sub sub item 2 + d) etc. + - Bulleted list item 3 + + +Note that a space after the list item markers (-, *, 1. etc.) are essential + +List items can span multiple lines: > + * Item 1 + Item 1 continued line. + Item 1 next continued line. + * Item 2 + - Sub item 1 + Sub item 1 continued line. + Sub item 1 next continued line. + - Sub item 2 + - etc. + Continuation of Item 2 + Next continuation of Item 2 -Multiline list items: > - * Bulleted list item 1 - List item 1 continued line. - List item 1 next continued line. - * Bulleted list item 2 - * Bulleted list sub item 1 - List sub item 1 continued line. - List sub item 1 next continued line. - * Bulleted list sub item 2 - * etc. Definition lists: > -Term 1:: Definition 1 -Term 2:: -:: Definition 2 -:: Definition 3 + Term 1:: Definition 1 + Term 2:: + :: Definition 2 + :: Definition 3 ------------------------------------------------------------------------------ @@ -1702,14 +1783,23 @@ Default: 0 Checked list items can be highlighted with a color: * [X] the whole line can be highlighted with the option set to 1. + * this line is highlighted as well with the option set to 2 * [ ] I wish vim could use strikethru. Value Description~ -1 Highlight checked [X] check box with |group-name| "Comment". -0 Don't. +0 Don't highlight anything. +1 Highlight checked [X] list item with |group-name| "Comment". +2 Highlight checked [X] list item and all its child items. Default: 0 +Note: Option 2 does not work perfectly. Specifically, it might break on +preformatted text or if you mix tabs and spaces for indenting, and indented +headers will erroneously be highlighted. +Furthermore, if your list is long, Vim's highlight can break. Consider putting +> + au BufEnter file.wiki :syntax sync fromstart +in your .vimrc ------------------------------------------------------------------------------ *g:vimwiki_global_ext* @@ -1786,12 +1876,15 @@ Default: 'Vimwiki' ------------------------------------------------------------------------------ *g:vimwiki_listsyms* -String of 5 symbols for list items with checkboxes. -Default value is ' .oOX'. +List of 5 symbols for list items with checkboxes. +Default value is [' ', '.', 'o', 'O', 'X']. g:vimwiki_listsyms[0] is for 0% done items. g:vimwiki_listsyms[4] is for 100% done items. +You can set it to some more fancy symbols like this: + + let g:vimwiki_listsyms = ['✗', '○', '◐', '●', '✓'] ------------------------------------------------------------------------------ *g:vimwiki_use_mouse* diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim @@ -8,10 +8,12 @@ if exists("b:did_ftplugin") endif let b:did_ftplugin = 1 " Don't load another plugin for this buffer +call vimwiki#u#reload_regexes() + " UNDO list {{{ " Reset the following options to undo this plugin. let b:undo_ftplugin = "setlocal ". - \ "suffixesadd< isfname< comments< ". + \ "suffixesadd< isfname< formatlistpat< ". \ "formatoptions< foldtext< ". \ "foldmethod< foldexpr< commentstring< " " UNDO }}} @@ -32,153 +34,45 @@ setlocal isfname-=[,] " gf}}} " Autocreate list items {{{ -" for list items, and list items with checkboxes -setlocal formatoptions+=tnro -setlocal formatoptions-=cq -if VimwikiGet('syntax') == 'default' - setl comments=b:*,b:#,b:- - setl formatlistpat=^\\s*[*#-]\\s* -elseif VimwikiGet('syntax') == 'markdown' - setlocal comments=fb:*,fb:-,fb:+,nb:> commentstring=\ >\ %s - setlocal formatlistpat=^\\s*\\d\\+\\.\\s\\+\\\|^[-*+]\\s\\+j -else - setl comments=n:*,n:# -endif +" for bulleted and numbered list items, and list items with checkboxes +setlocal autoindent +setlocal nosmartindent +setlocal nocindent +setlocal comments="" +setlocal formatoptions-=c +setlocal formatoptions-=r +setlocal formatoptions-=o +setlocal formatoptions-=2 +setlocal formatoptions+=n + + +"Create 'formatlistpat' +let &formatlistpat = g:vimwiki_rxListItem + if !empty(&langmap) " Valid only if langmap is a comma separated pairs of chars let l_o = matchstr(&langmap, '\C,\zs.\zeo,') if l_o - exe 'nnoremap <buffer> '.l_o.' :call vimwiki#lst#kbd_oO("o")<CR>a' + exe 'nnoremap <buffer> '.l_o.' :call vimwiki#lst#kbd_o()<CR>a' endif let l_O = matchstr(&langmap, '\C,\zs.\zeO,') if l_O - exe 'nnoremap <buffer> '.l_O.' :call vimwiki#lst#kbd_oO("O")<CR>a' + exe 'nnoremap <buffer> '.l_O.' :call vimwiki#lst#kbd_O()<CR>a' endif endif " COMMENTS }}} -" FOLDING for headers and list items using expr fold method. {{{ - -" Folding list items using expr fold method. {{{ - -function! s:get_base_level(lnum) "{{{ - let lnum = a:lnum - 1 - while lnum > 0 - if getline(lnum) =~ g:vimwiki_rxHeader - return vimwiki#u#count_first_sym(getline(lnum)) - endif - let lnum -= 1 - endwhile - return 0 -endfunction "}}} - -function! s:find_forward(rx_item, lnum) "{{{ - let lnum = a:lnum + 1 - - while lnum <= line('$') - let line = getline(lnum) - if line =~ a:rx_item - \ || line =~ '^\S' - \ || line =~ g:vimwiki_rxHeader - break - endif - let lnum += 1 - endwhile - - return [lnum, getline(lnum)] -endfunction "}}} - -function! s:find_backward(rx_item, lnum) "{{{ - let lnum = a:lnum - 1 - - while lnum > 1 - let line = getline(lnum) - if line =~ a:rx_item - \ || line =~ '^\S' - break - endif - let lnum -= 1 - endwhile - - return [lnum, getline(lnum)] -endfunction "}}} - -function! s:get_li_level(lnum) "{{{ - if VimwikiGet('syntax') == 'media' - let level = vimwiki#u#count_first_sym(getline(a:lnum)) - else - let level = (indent(a:lnum) / &sw) - endif - return level -endfunction "}}} - -function! s:get_start_list(rx_item, lnum) "{{{ - let lnum = a:lnum - while lnum >= 1 - let line = getline(lnum) - if line !~ a:rx_item && line =~ '^\S' - return nextnonblank(lnum + 1) - endif - let lnum -= 1 - endwhile - return 0 -endfunction "}}} - +" FOLDING {{{ +" Folding list items {{{ function! VimwikiFoldListLevel(lnum) "{{{ - let line = getline(a:lnum) - - "" XXX Disabled: Header/section folding... - "if line =~ g:vimwiki_rxHeader - " return '>'.vimwiki#u#count_first_sym(line) - "endif - - "let nnline = getline(a:lnum+1) - - "" Unnecessary? - "if nnline =~ g:vimwiki_rxHeader - " return '<'.vimwiki#u#count_first_sym(nnline) - "endif - "" Very slow when called on every single line! - "let base_level = s:get_base_level(a:lnum) - - "FIXME does not work correctly - let base_level = 0 - - if line =~ g:vimwiki_rxListItem - let [nnum, nline] = s:find_forward(g:vimwiki_rxListItem, a:lnum) - let level = s:get_li_level(a:lnum) - let leveln = s:get_li_level(nnum) - let adj = s:get_li_level(s:get_start_list(g:vimwiki_rxListItem, a:lnum)) - - if leveln > level - return ">".(base_level+leveln-adj) - " check if multilined list item - elseif (nnum-a:lnum) > 1 - \ && (nline =~ g:vimwiki_rxListItem || nnline !~ '^\s*$') - return ">".(base_level+level+1-adj) - else - return (base_level+level-adj) - endif - else - " process multilined list items - let [pnum, pline] = s:find_backward(g:vimwiki_rxListItem, a:lnum) - if pline =~ g:vimwiki_rxListItem - if indent(a:lnum) >= indent(pnum) && line !~ '^\s*$' - let level = s:get_li_level(pnum) - let adj = s:get_li_level(s:get_start_list(g:vimwiki_rxListItem, pnum)) - return (base_level+level+1-adj) - endif - endif - endif - - return base_level + return vimwiki#lst#fold_level(a:lnum) endfunction "}}} " Folding list items }}} -" Folding sections and code blocks using expr fold method. {{{ +" Folding sections and code blocks {{{ function! VimwikiFoldLevel(lnum) "{{{ let line = getline(a:lnum) @@ -277,7 +171,7 @@ command! -buffer -nargs=? VimwikiNormalizeLink call vimwiki#base#normalize_link( command! -buffer VimwikiTabnewLink call vimwiki#base#follow_link('tabnew') -command! -buffer -range VimwikiToggleListItem call vimwiki#lst#ToggleListItem(<line1>, <line2>) +command! -buffer -range VimwikiToggleCheckbox call vimwiki#lst#toggle_cb(<line1>, <line2>) command! -buffer VimwikiGenerateLinks call vimwiki#base#generate_links() @@ -294,7 +188,12 @@ command! -buffer -nargs=1 VimwikiGoto call vimwiki#base#goto("<args>") " list commands -command! -buffer -nargs=* VimwikiListChangeLevel call vimwiki#lst#change_level(<f-args>) +command! -buffer -range -nargs=1 VimwikiListChangeMarker call vimwiki#lst#change_marker(<line1>, <line2>, <f-args>) +command! -buffer -nargs=1 VimwikiListChangeMarkerInList call vimwiki#lst#change_marker_in_list(<f-args>) +command! -buffer -nargs=+ VimwikiListLineBreak call <SID>CR(<f-args>) +command! -buffer -range -nargs=1 VimwikiListIncreaseLvl call vimwiki#lst#change_level(<line1>, <line2>, 'increase', <f-args>) +command! -buffer -range -nargs=1 VimwikiListDecreaseLvl call vimwiki#lst#change_level(<line1>, <line2>, 'decrease', <f-args>) +command! -buffer -range VimwikiListRemoveCB call vimwiki#lst#remove_cb(<line1>, <line2>) " table commands command! -buffer -nargs=* VimwikiTable call vimwiki#tbl#create(<f-args>) @@ -405,15 +304,18 @@ endif nnoremap <silent><script><buffer> \ <Plug>VimwikiRenameLink :VimwikiRenameLink<CR> -if !hasmapto('<Plug>VimwikiToggleListItem') - nmap <silent><buffer> <C-Space> <Plug>VimwikiToggleListItem - vmap <silent><buffer> <C-Space> <Plug>VimwikiToggleListItem +if !hasmapto('<Plug>VimwikiToggleCheckbox') + nmap <silent><buffer> <C-Space> <Plug>VimwikiToggleCheckbox + vmap <silent><buffer> <C-Space> <Plug>VimwikiToggleCheckbox if has("unix") - nmap <silent><buffer> <C-@> <Plug>VimwikiToggleListItem + nmap <silent><buffer> <C-@> <Plug>VimwikiToggleCheckbox + vmap <silent><buffer> <C-@> <Plug>VimwikiToggleCheckbox endif endif nnoremap <silent><script><buffer> - \ <Plug>VimwikiToggleListItem :VimwikiToggleListItem<CR> + \ <Plug>VimwikiToggleCheckbox :VimwikiToggleCheckbox<CR> +vnoremap <silent><script><buffer> + \ <Plug>VimwikiToggleCheckbox :VimwikiToggleCheckbox<CR> if !hasmapto('<Plug>VimwikiDiaryNextDay') nmap <silent><buffer> <C-Down> <Plug>VimwikiDiaryNextDay @@ -427,42 +329,58 @@ endif nnoremap <silent><script><buffer> \ <Plug>VimwikiDiaryPrevDay :VimwikiDiaryPrevDay<CR> -function! s:CR() "{{{ - let res = vimwiki#lst#kbd_cr() - if res == "\<CR>" && g:vimwiki_table_mappings +function! s:CR(normal, just_mrkr) "{{{ + if g:vimwiki_table_mappings let res = vimwiki#tbl#kbd_cr() + if res != "" + exe "normal! " . res . "\<Right>" + startinsert + return + endif endif - return res + call vimwiki#lst#kbd_cr(a:normal, a:just_mrkr) endfunction "}}} -" List and Table <CR> mapping -inoremap <buffer> <expr> <CR> <SID>CR() - " List mappings -nnoremap <buffer> o :<C-U>call vimwiki#lst#kbd_oO('o')<CR> -nnoremap <buffer> O :<C-U>call vimwiki#lst#kbd_oO('O')<CR> -nnoremap <buffer> gll :VimwikiListChangeLevel <<<CR> -nnoremap <buffer> glm :VimwikiListChangeLevel >><CR> -nnoremap <buffer> gl* :VimwikiListChangeLevel *<CR> -nnoremap <buffer> gl8 :VimwikiListChangeLevel *<CR> -if VimwikiGet('syntax') == 'default' - nnoremap <buffer> gl- :VimwikiListChangeLevel -<CR> - nnoremap <buffer> gl# :VimwikiListChangeLevel #<CR> - nnoremap <buffer> gl3 :VimwikiListChangeLevel #<CR> -elseif VimwikiGet('syntax') == 'markdown' - nnoremap <buffer> gl- :VimwikiListChangeLevel -<CR> - nnoremap <buffer> gl1 :VimwikiListChangeLevel 1.<CR> -elseif VimwikiGet('syntax') == 'media' - nnoremap <buffer> gl# :VimwikiListChangeLevel #<CR> - nnoremap <buffer> gl3 :VimwikiListChangeLevel #<CR> -endif +inoremap <buffer> <CR> <Esc>:VimwikiListLineBreak 1 5<CR> +inoremap <buffer> <S-CR> <Esc>:VimwikiListLineBreak 2 2<CR> +nnoremap <silent> <buffer> o :call vimwiki#lst#kbd_o()<CR> +nnoremap <silent> <buffer> O :call vimwiki#lst#kbd_O()<CR> +map <silent> <buffer> glh :VimwikiListDecreaseLvl 0<CR> +map <silent> <buffer> gll :VimwikiListIncreaseLvl 0<CR> +map <silent> <buffer> gLh :VimwikiListDecreaseLvl 1<CR> +map <silent> <buffer> gLl :VimwikiListIncreaseLvl 1<CR> +map <silent> <buffer> gLH glH +map <silent> <buffer> gLL gLl +inoremap <buffer> <C-D> <C-O>:VimwikiListDecreaseLvl 0<CR> +inoremap <buffer> <C-T> <C-O>:VimwikiListIncreaseLvl 0<CR> +inoremap <buffer> <C-L><C-J> <C-O>:VimwikiListChangeMarker next<CR> +inoremap <buffer> <C-L><C-K> <C-O>:VimwikiListChangeMarker prev<CR> +nmap <silent> <buffer> glr :call vimwiki#lst#adjust_numbered_list()<CR> +nmap <silent> <buffer> gLr :call vimwiki#lst#adjust_whole_buffer()<CR> +nmap <silent> <buffer> gLR gLr +noremap <silent> <buffer> gl<Space> :VimwikiListRemoveCB<CR> +map <silent> <buffer> gL<Space> :call vimwiki#lst#remove_cb_in_list()<CR> +inoremap <silent> <buffer> <C-L><C-M> <Esc>:call vimwiki#lst#toggle_list_item()<CR> + +for s:k in keys(g:vimwiki_bullet_types) + let s:char = (s:k == '•' ? '.' : s:k) + exe 'noremap <silent> <buffer> gl'.s:char.' :VimwikiListChangeMarker '.s:k.'<CR>' + exe 'noremap <silent> <buffer> gL'.s:char.' :VimwikiListChangeMarkerInList '.s:k.'<CR>' +endfor +for s:k in g:vimwiki_number_types + exe 'noremap <silent> <buffer> gl'.s:k[0].' :VimwikiListChangeMarker '.s:k.'<CR>' + exe 'noremap <silent> <buffer> gL'.s:k[0].' :VimwikiListChangeMarkerInList '.s:k.'<CR>' +endfor + + +"Table mappings + if g:vimwiki_table_mappings + inoremap <expr> <buffer> <Tab> vimwiki#tbl#kbd_tab() + inoremap <expr> <buffer> <S-Tab> vimwiki#tbl#kbd_shift_tab() + endif -" Table mappings -if g:vimwiki_table_mappings - inoremap <expr> <buffer> <Tab> vimwiki#tbl#kbd_tab() - inoremap <expr> <buffer> <S-Tab> vimwiki#tbl#kbd_shift_tab() -endif nnoremap <buffer> gqq :VimwikiTableAlignQ<CR> nnoremap <buffer> gww :VimwikiTableAlignW<CR> diff --git a/plugin/vimwiki.vim b/plugin/vimwiki.vim @@ -392,7 +392,7 @@ call s:default('ext2syntax', {}) " syntax map keyed on extension call s:default('hl_headers', 0) call s:default('hl_cb_checked', 0) call s:default('list_ignore_newline', 1) -call s:default('listsyms', ' .oOX') +call s:default('listsyms', [' ', '.', 'o', 'O', 'X']) call s:default('use_calendar', 1) call s:default('table_mappings', 1) call s:default('table_auto_fmt', 1) diff --git a/syntax/vimwiki.vim b/syntax/vimwiki.vim @@ -9,6 +9,7 @@ if version < 600 elseif exists("b:current_syntax") finish endif + "TODO do nothing if ...? (?) let starttime = reltime() " start the clock if VimwikiGet('maxhi') @@ -43,15 +44,9 @@ let g:vimwiki_rxWeblinkUrl = g:vimwiki_rxWebProtocols . " }}} -" ------------------------------------------------------------------------- -" Load concrete Wiki syntax: sets regexes and templates for headers and links -execute 'runtime! syntax/vimwiki_'.VimwikiGet('syntax').'.vim' -" ------------------------------------------------------------------------- -let time0 = vimwiki#u#time(starttime) "XXX +call vimwiki#u#reload_regexes() -let g:vimwiki_rxListItem = '\('. - \ g:vimwiki_rxListBullet.'\|'.g:vimwiki_rxListNumber. - \ '\)' +let time0 = vimwiki#u#time(starttime) "XXX " LINKS: setup of larger regexes {{{ @@ -67,12 +62,11 @@ let g:vimwiki_WikiLinkTemplate2 = g:vimwiki_rxWikiLinkPrefix . '__LinkUrl__'. \ g:vimwiki_rxWikiLinkSeparator. '__LinkDescription__'. \ g:vimwiki_rxWikiLinkSuffix " -let magic_chars = '.*[]\^$' let valid_chars = '[^\\\]]' -let g:vimwiki_rxWikiLinkPrefix = escape(g:vimwiki_rxWikiLinkPrefix, magic_chars) -let g:vimwiki_rxWikiLinkSuffix = escape(g:vimwiki_rxWikiLinkSuffix, magic_chars) -let g:vimwiki_rxWikiLinkSeparator = escape(g:vimwiki_rxWikiLinkSeparator, magic_chars) +let g:vimwiki_rxWikiLinkPrefix = vimwiki#u#escape(g:vimwiki_rxWikiLinkPrefix) +let g:vimwiki_rxWikiLinkSuffix = vimwiki#u#escape(g:vimwiki_rxWikiLinkSuffix) +let g:vimwiki_rxWikiLinkSeparator = vimwiki#u#escape(g:vimwiki_rxWikiLinkSeparator) let g:vimwiki_rxWikiLinkUrl = valid_chars.'\{-}' let g:vimwiki_rxWikiLinkDescr = valid_chars.'\{-}' @@ -116,9 +110,9 @@ let g:vimwiki_WikiInclTemplate2 = g:vimwiki_rxWikiInclPrefix . '__LinkUrl__'. let valid_chars = '[^\\\}]' -let g:vimwiki_rxWikiInclPrefix = escape(g:vimwiki_rxWikiInclPrefix, magic_chars) -let g:vimwiki_rxWikiInclSuffix = escape(g:vimwiki_rxWikiInclSuffix, magic_chars) -let g:vimwiki_rxWikiInclSeparator = escape(g:vimwiki_rxWikiInclSeparator, magic_chars) +let g:vimwiki_rxWikiInclPrefix = vimwiki#u#escape(g:vimwiki_rxWikiInclPrefix) +let g:vimwiki_rxWikiInclSuffix = vimwiki#u#escape(g:vimwiki_rxWikiInclSuffix) +let g:vimwiki_rxWikiInclSeparator = vimwiki#u#escape(g:vimwiki_rxWikiInclSeparator) let g:vimwiki_rxWikiInclUrl = valid_chars.'\{-}' let g:vimwiki_rxWikiInclArg = valid_chars.'\{-}' let g:vimwiki_rxWikiInclArgs = '\%('. g:vimwiki_rxWikiInclSeparator. g:vimwiki_rxWikiInclArg. '\)'.'\{-}' @@ -279,7 +273,6 @@ call s:add_target_syntax_ON(target, 'VimwikiLink') " }}} - " generic headers "{{{ if g:vimwiki_symH "" symmetric @@ -405,25 +398,19 @@ syntax match VimwikiTableRow /^\s*|.\+|\s*$/ syntax match VimwikiCellSeparator \ /\%(|\)\|\%(-\@<=+\-\@=\)\|\%([|+]\@<=-\+\)/ contained -" List items -execute 'syntax match VimwikiList /'.g:vimwiki_rxListBullet.'/' -execute 'syntax match VimwikiList /'.g:vimwiki_rxListNumber.'/' +" Lists +execute 'syntax match VimwikiList /'.g:vimwiki_rxListItemWithoutCB.'/' execute 'syntax match VimwikiList /'.g:vimwiki_rxListDefine.'/' -" List item checkbox -"syntax match VimwikiCheckBox /\[.\?\]/ -let g:vimwiki_rxCheckBox = '\s*\[['.g:vimwiki_listsyms.']\?\]\s' -" Todo lists have a checkbox -execute 'syntax match VimwikiListTodo /'.g:vimwiki_rxListBullet.g:vimwiki_rxCheckBox.'/' -execute 'syntax match VimwikiListTodo /'.g:vimwiki_rxListNumber.g:vimwiki_rxCheckBox.'/' -if g:vimwiki_hl_cb_checked - execute 'syntax match VimwikiCheckBoxDone /'. - \ g:vimwiki_rxListBullet.'\s*\['.g:vimwiki_listsyms[4].'\]\s.*$/'. - \ ' contains=VimwikiNoExistsLink,VimwikiLink' - execute 'syntax match VimwikiCheckBoxDone /'. - \ g:vimwiki_rxListNumber.'\s*\['.g:vimwiki_listsyms[4].'\]\s.*$/'. - \ ' contains=VimwikiNoExistsLink,VimwikiLink' +execute 'syntax match VimwikiListTodo /'.g:vimwiki_rxListItem.'/' + +if g:vimwiki_hl_cb_checked == 1 + execute 'syntax match VimwikiCheckBoxDone /'.g:vimwiki_rxListItemWithoutCB.'\s*\['.g:vimwiki_listsyms[4].'\]\s.*$/ '. + \ 'contains=VimwikiNoExistsLink,VimwikiLink,@Spell' +elseif g:vimwiki_hl_cb_checked == 2 + execute 'syntax match VimwikiCheckBoxDone /'.g:vimwiki_rxListItemAndChildren.'/ contains=VimwikiNoExistsLink,VimwikiLink,@Spell' endif + execute 'syntax match VimwikiEqIn /'.g:vimwiki_rxEqIn.'/ contains=VimwikiEqInChar' execute 'syntax match VimwikiEqInT /'.g:vimwiki_rxEqIn.'/ contained contains=VimwikiEqInCharT' @@ -503,8 +490,6 @@ else endif "}}} - - " syntax group highlighting "{{{ hi def link VimwikiMarkers Normal @@ -542,7 +527,6 @@ hi def link VimwikiLinkT VimwikiLink hi def link VimwikiList Identifier hi def link VimwikiListTodo VimwikiList -"hi def link VimwikiCheckBox VimwikiList hi def link VimwikiCheckBoxDone Comment hi def link VimwikiEmoticons Character hi def link VimwikiHR Identifier @@ -589,10 +573,8 @@ hi def link VimwikiLinkCharT VimwikiLinkT hi def link VimwikiNoExistsLinkCharT VimwikiNoExistsLinkT "}}} -" ------------------------------------------------------------------------- " Load syntax-specific functionality -execute 'runtime! syntax/vimwiki_'.VimwikiGet('syntax').'_custom.vim' -" ------------------------------------------------------------------------- +call vimwiki#u#reload_regexes_custom() " FIXME it now does not make sense to pretend there is a single syntax "vimwiki" let b:current_syntax="vimwiki" diff --git a/syntax/vimwiki_default.vim b/syntax/vimwiki_default.vim @@ -72,11 +72,19 @@ let g:vimwiki_rxHR = '^-----*$' " Tables. Each line starts and ends with '|'; each cell is separated by '|' let g:vimwiki_rxTableSep = '|' -" List items start with optional whitespace(s) then '* ' or '# ' -let g:vimwiki_rxListBullet = '^\s*[*-]\s' -let g:vimwiki_rxListNumber = '^\s*#\s' - +" Lists +"1 means multiple bullets, like * ** *** +let g:vimwiki_bullet_types = { '-':0, '*':0, '#':0 , '•':0 } +let g:vimwiki_number_types = ['1)', '1.', 'i)', 'I)', 'a)', 'A)'] +"this should contain at least one element +"it is used for i_<C-L><C-J> among other things +let g:vimwiki_list_markers = ['-', '•', '1.', '*', 'I)', 'a)'] let g:vimwiki_rxListDefine = '::\(\s\|$\)' +call vimwiki#lst#setup_marker_infos() + +let g:vimwiki_rxListItemWithoutCB = '^\s*\%(\('.g:vimwiki_rxListBullet.'\)\|\('.g:vimwiki_rxListNumber.'\)\)\s' +let g:vimwiki_rxListItem = g:vimwiki_rxListItemWithoutCB . '\+\%(\[\(['.join(g:vimwiki_listsyms, '').']\)\]\s\)\?' +let g:vimwiki_rxListItemAndChildren = '^\(\s*\)\%('.g:vimwiki_rxListBullet.'\|'.g:vimwiki_rxListNumber.'\)\s\+\['.g:vimwiki_listsyms[4].'\]\s.*\%(\n\%(\1\s.*\|^$\)\)*' " Preformatted text let g:vimwiki_rxPreStart = '{{{' diff --git a/syntax/vimwiki_markdown.vim b/syntax/vimwiki_markdown.vim @@ -72,11 +72,16 @@ let g:vimwiki_rxHR = '^-----*$' " Tables. Each line starts and ends with '|'; each cell is separated by '|' let g:vimwiki_rxTableSep = '|' -" List items start with optional whitespace(s) then '* ' or '1. ', '2. ', etc. -let g:vimwiki_rxListBullet = '^\s*[*+-]\s' -let g:vimwiki_rxListNumber = '^\s*[0-9]\+\.\s' - +" Lists +let g:vimwiki_bullet_types = { '-':0, '*':0, '+':0 } +let g:vimwiki_number_types = ['1.'] +let g:vimwiki_list_markers = ['-', '*', '+', '1.'] let g:vimwiki_rxListDefine = '::\%(\s\|$\)' +call vimwiki#lst#setup_marker_infos() + +let g:vimwiki_rxListItemWithoutCB = '^\s*\%(\('.g:vimwiki_rxListBullet.'\)\|\('.g:vimwiki_rxListNumber.'\)\)\s' +let g:vimwiki_rxListItem = g:vimwiki_rxListItemWithoutCB . '\+\%(\[\(['.join(g:vimwiki_listsyms, '').']\)\]\s\)\?' +let g:vimwiki_rxListItemAndChildren = '^\(\s*\)\%('.g:vimwiki_rxListBullet.'\|'.g:vimwiki_rxListNumber.'\)\s\+\['.g:vimwiki_listsyms[4].'\]\s.*\%(\n\%(\1\s.*\|^$\)\)*' " Preformatted text let g:vimwiki_rxPreStart = '```' diff --git a/syntax/vimwiki_markdown_custom.vim b/syntax/vimwiki_markdown_custom.vim @@ -42,12 +42,11 @@ let g:vimwiki_WikiLink1Template2 = g:vimwiki_rxWikiLink1Prefix . '__LinkDescript \ g:vimwiki_rxWikiLink1Separator. '__LinkUrl__'. \ g:vimwiki_rxWikiLink1Suffix " -let magic_chars = '.*[]\^$' let valid_chars = '[^\\\[\]]' -let g:vimwiki_rxWikiLink1Prefix = escape(g:vimwiki_rxWikiLink1Prefix, magic_chars) -let g:vimwiki_rxWikiLink1Suffix = escape(g:vimwiki_rxWikiLink1Suffix, magic_chars) -let g:vimwiki_rxWikiLink1Separator = escape(g:vimwiki_rxWikiLink1Separator, magic_chars) +let g:vimwiki_rxWikiLink1Prefix = vimwiki#u#escape(g:vimwiki_rxWikiLink1Prefix) +let g:vimwiki_rxWikiLink1Suffix = vimwiki#u#escape(g:vimwiki_rxWikiLink1Suffix) +let g:vimwiki_rxWikiLink1Separator = vimwiki#u#escape(g:vimwiki_rxWikiLink1Separator) let g:vimwiki_rxWikiLink1Url = valid_chars.'\{-}' let g:vimwiki_rxWikiLink1Descr = valid_chars.'\{-}' @@ -125,12 +124,11 @@ let g:vimwiki_Weblink1Template = g:vimwiki_rxWeblink1Prefix . '__LinkDescription \ g:vimwiki_rxWeblink1Separator. '__LinkUrl__'. \ g:vimwiki_rxWeblink1Suffix -let magic_chars = '.*[]\^$' let valid_chars = '[^\\]' -let g:vimwiki_rxWeblink1Prefix = escape(g:vimwiki_rxWeblink1Prefix, magic_chars) -let g:vimwiki_rxWeblink1Suffix = escape(g:vimwiki_rxWeblink1Suffix, magic_chars) -let g:vimwiki_rxWeblink1Separator = escape(g:vimwiki_rxWeblink1Separator, magic_chars) +let g:vimwiki_rxWeblink1Prefix = vimwiki#u#escape(g:vimwiki_rxWeblink1Prefix) +let g:vimwiki_rxWeblink1Suffix = vimwiki#u#escape(g:vimwiki_rxWeblink1Suffix) +let g:vimwiki_rxWeblink1Separator = vimwiki#u#escape(g:vimwiki_rxWeblink1Separator) let g:vimwiki_rxWeblink1Url = valid_chars.'\{-}' let g:vimwiki_rxWeblink1Descr = valid_chars.'\{-}' diff --git a/syntax/vimwiki_media.vim b/syntax/vimwiki_media.vim @@ -53,12 +53,16 @@ let g:vimwiki_rxHR = '^-----*$' " Tables. Each line starts and ends with '|'; each cell is separated by '|' let g:vimwiki_rxTableSep = '|' -" Bulleted list items start with whitespace(s), then '*' -" highlight only bullets and digits. -let g:vimwiki_rxListBullet = '^\s*\*\+\s\%([^*]*$\)\@=' -let g:vimwiki_rxListNumber = '^\s*#\+\s' - +" Lists +let g:vimwiki_bullet_types = { '*':1, '#':1 } +let g:vimwiki_number_types = [] +let g:vimwiki_list_markers = ['*', '#'] let g:vimwiki_rxListDefine = '^\%(;\|:\)\s' +call vimwiki#lst#setup_marker_infos() + +let g:vimwiki_rxListItemWithoutCB = '^\s*\%(\('.g:vimwiki_rxListBullet.'\)\|\('.g:vimwiki_rxListNumber.'\)\)\s' +let g:vimwiki_rxListItem = g:vimwiki_rxListItemWithoutCB . '\+\%(\[\(['.join(g:vimwiki_listsyms, '').']\)\]\s\)\?' +let g:vimwiki_rxListItemAndChildren = '^\(\s*\)\%('.g:vimwiki_rxListBullet.'\|'.g:vimwiki_rxListNumber.'\)\s\+\['.g:vimwiki_listsyms[4].'\]\s.*\%(\n\%(\1\s.*\|^$\)\)*' " Preformatted text let g:vimwiki_rxPreStart = '<pre>'