diff --git a/README.md b/README.md
index a1501c1..6645ad5 100644
--- a/README.md
+++ b/README.md
@@ -397,7 +397,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
mykoza 💻 🤔 |
noodlor 💻 |
- Harshad Srinivasan 💻 🐛 |
+ Harshad Vedartham 💻 🐛 |
Erick A. Chacón Montalván 🤔 |
Sam Griesemer 💻 🐛 |
Charles Pence 💻 |
diff --git a/plugin/bullets.vim b/plugin/bullets.vim
index e5e017f..fd0560e 100644
--- a/plugin/bullets.vim
+++ b/plugin/bullets.vim
@@ -90,6 +90,10 @@ if !exists('g:bullets_nested_checkboxes')
let g:bullets_nested_checkboxes = 1
endif
+if !exists('g:bullets_enable_wrapped_lines')
+ let g:bullets_enable_wrapped_lines = 1
+end
+
if !exists('g:bullets_checkbox_markers')
" The ordered series of markers to use in checkboxes
" If only two markers are listed, they represent 'off' and 'on'
@@ -121,7 +125,48 @@ endif
" ------------------------------------------------------ }}}
" Parse Bullet Type ------------------------------------------- {{{
+
+" A caching mechanism for bullet
+" We add a crude 'reference count' for the cache so we can nest calls
+let s:bullet_cache = v:null
+let s:bullet_cache_depth = 0
+
+fun! s:enable_bullet_cache()
+ if s:bullet_cache_depth == 0
+ let s:bullet_cache = {}
+ endif
+ let s:bullet_cache_depth += 1
+endfun
+
+fun! s:disable_bullet_cache()
+ if s:bullet_cache_depth == 1
+ let s:bullet_cache = v:null
+ endif
+
+ if s:bullet_cache_depth > 0
+ let s:bullet_cache_depth -= 1
+ endif
+endfun
+
fun! s:parse_bullet(line_num, line_text)
+ let l:kinds = s:parse_bullet_text(a:line_text)
+
+ for l:data in l:kinds
+ let l:data.starting_at_line_num = a:line_num
+ endfor
+
+ return l:kinds
+endfun
+
+fun! s:parse_bullet_text(line_text)
+
+ if s:bullet_cache isnot v:null
+ let l:cached = get(s:bullet_cache, a:line_text, v:null)
+ if l:cached isnot v:null
+ " Return a copy so as not to break the referene
+ return copy(l:cached)
+ endif
+ endif
let l:bullet = s:match_bullet_list_item(a:line_text)
" Must be a bullet to be a checkbox
@@ -134,13 +179,12 @@ fun! s:parse_bullet(line_num, line_text)
let l:roman = empty(l:bullet) && empty(l:num) ? s:match_roman_list_item(a:line_text) : {}
let l:kinds = s:filter([l:bullet, l:check, l:num, l:alpha, l:roman], '!empty(v:val)')
-
- for l:data in l:kinds
- let l:data.starting_at_line_num = a:line_num
- endfor
-
+
+ if s:bullet_cache isnot v:null
+ let s:bullet_cache[a:line_text] = l:kinds
+ endif
+
return l:kinds
-
endfun
fun! s:match_numeric_list_item(input_text)
@@ -371,17 +415,19 @@ fun! s:closest_bullet_types(from_line_num, max_indent)
" Support for wrapped text bullets, even if the wrapped line is not indented
" It considers a blank line as the end of a bullet
" DEMO: https://raw.githubusercontent.com/dkarter/bullets.vim/master/img/wrapped-bullets.gif
- while l:lnum > 1 && (l:curr_indent != 0 || l:bullet_kinds != [] || !(l:ltxt =~# '\v^(\s+$|$)'))
- \ && (a:max_indent < l:curr_indent || l:bullet_kinds == [])
- if l:bullet_kinds != []
- let l:lnum = l:lnum - g:bullets_line_spacing
- else
- let l:lnum = l:lnum - 1
- endif
- let l:ltxt = getline(l:lnum)
- let l:bullet_kinds = s:parse_bullet(l:lnum, l:ltxt)
- let l:curr_indent = indent(l:lnum)
- endwhile
+ if g:bullets_enable_wrapped_lines
+ while l:lnum > 1 && (l:curr_indent != 0 || l:bullet_kinds != [] || !(l:ltxt =~# '\v^(\s+$|$)'))
+ \ && (a:max_indent < l:curr_indent || l:bullet_kinds == [])
+ if l:bullet_kinds != []
+ let l:lnum = l:lnum - g:bullets_line_spacing
+ else
+ let l:lnum = l:lnum - 1
+ endif
+ let l:ltxt = getline(l:lnum)
+ let l:bullet_kinds = s:parse_bullet(l:lnum, l:ltxt)
+ let l:curr_indent = indent(l:lnum)
+ endwhile
+ endif
return l:bullet_kinds
endfun
@@ -819,6 +865,7 @@ fun! s:renumber_selection()
endfun
fun! s:renumber_lines(start, end)
+ call s:enable_bullet_cache()
let l:prev_indent = -1
let l:levels = {} " stores all the info about the current outline/list
@@ -896,15 +943,18 @@ fun! s:renumber_lines(start, end)
endif
endif
endfor
+ call s:disable_bullet_cache()
endfun
" Renumbers the whole list containing the cursor.
fun! s:renumber_whole_list()
+ call s:enable_bullet_cache()
let l:first_line = s:first_bullet_line(line('.'))
let l:last_line = s:last_bullet_line(line('.'))
if l:first_line > 0 && l:last_line > 0
call s:renumber_lines(l:first_line, l:last_line)
endif
+ call s:disable_bullet_cache()
endfun
command! -range=% RenumberSelection call renumber_selection()