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:
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>'