mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-01-24 05:40:05 +08:00
209 lines
5.9 KiB
VimL
209 lines
5.9 KiB
VimL
if !exists("g:line_map")
|
|
let g:line_map = {} " 'line_nr' => 'bookmark'
|
|
let g:sign_map = {} " 'sign_idx' => 'line_nr'
|
|
endif
|
|
|
|
" Bookmark Model {{{
|
|
|
|
function! bm#has_bookmarks_in_file(file)
|
|
if !has_key(g:line_map, a:file)
|
|
return 0
|
|
endif
|
|
return len(keys(g:line_map[a:file])) > 0
|
|
endfunction
|
|
|
|
function! bm#has_bookmark_at_line(file, line_nr)
|
|
if !has_key(g:line_map, a:file)
|
|
return 0
|
|
endif
|
|
return has_key(g:line_map[a:file], a:line_nr)
|
|
endfunction
|
|
|
|
function! bm#get_bookmark_by_line(file, line_nr)
|
|
return g:line_map[a:file][a:line_nr]
|
|
endfunction
|
|
|
|
function! bm#is_bookmark_has_annotation_by_line(file, line_nr)
|
|
return g:line_map[a:file][a:line_nr]['annotation'] !=# ""
|
|
endfunction
|
|
|
|
function! bm#get_bookmark_by_sign(file, sign_idx)
|
|
let line_nr = g:sign_map[a:file][a:sign_idx]
|
|
return bm#get_bookmark_by_line(a:file, line_nr)
|
|
endfunction
|
|
|
|
function! bm#add_bookmark(file, sign_idx, line_nr, content, ...)
|
|
if !has_key(g:line_map, a:file)
|
|
let g:line_map[a:file] = {}
|
|
let g:sign_map[a:file] = {}
|
|
endif
|
|
let annotation = a:0 ==# 1 ? a:1 : ""
|
|
let entry = {'sign_idx': a:sign_idx, 'line_nr': a:line_nr, 'content': a:content, 'annotation': annotation}
|
|
let g:line_map[a:file][a:line_nr] = entry
|
|
let g:sign_map[a:file][a:sign_idx] = a:line_nr
|
|
return entry
|
|
endfunction
|
|
|
|
function! bm#update_bookmark_for_sign(file, sign_idx, new_line_nr, new_content)
|
|
let bookmark = bm#get_bookmark_by_sign(a:file, a:sign_idx)
|
|
call bm#del_bookmark_at_line(a:file, bookmark['line_nr'])
|
|
call bm#add_bookmark(a:file, a:sign_idx, a:new_line_nr, a:new_content, bookmark['annotation'])
|
|
endfunction
|
|
|
|
function! bm#update_annotation(file, sign_idx, annotation)
|
|
let bookmark = bm#get_bookmark_by_sign(a:file, a:sign_idx)
|
|
let bookmark['annotation'] = a:annotation
|
|
endfunction
|
|
|
|
function! bm#next(file, current_line_nr)
|
|
let line_nrs = sort(bm#all_lines(a:file), "bm#compare_lines")
|
|
if empty(line_nrs)
|
|
return 0
|
|
endif
|
|
if a:current_line_nr >=# line_nrs[-1] || a:current_line_nr <# line_nrs[0]
|
|
return line_nrs[0] + 0
|
|
else
|
|
let idx = 0
|
|
let lines_count = len(line_nrs)
|
|
while idx <# lines_count-1
|
|
let cur_bookmark = line_nrs[idx]
|
|
let next_bookmark = line_nrs[idx+1]
|
|
if a:current_line_nr >=# cur_bookmark && a:current_line_nr <# next_bookmark
|
|
return next_bookmark + 0
|
|
endif
|
|
let idx = idx+1
|
|
endwhile
|
|
endif
|
|
return 0
|
|
endfunction
|
|
|
|
function! bm#prev(file, current_line_nr)
|
|
let line_nrs = sort(bm#all_lines(a:file), "bm#compare_lines")
|
|
if empty(line_nrs)
|
|
return 0
|
|
endif
|
|
let lines_count = len(line_nrs)
|
|
let idx = lines_count-1
|
|
if a:current_line_nr <=# line_nrs[0] || a:current_line_nr ># line_nrs[-1]
|
|
return line_nrs[idx] + 0
|
|
else
|
|
while idx >=# 0
|
|
let cur_bookmark = line_nrs[idx]
|
|
let next_bookmark = line_nrs[idx-1]
|
|
if a:current_line_nr <=# cur_bookmark && a:current_line_nr ># next_bookmark
|
|
return next_bookmark + 0
|
|
endif
|
|
let idx = idx-1
|
|
endwhile
|
|
endif
|
|
return 0
|
|
endfunction
|
|
|
|
function! bm#del_bookmark_at_line(file, line_nr)
|
|
let bookmark = bm#get_bookmark_by_line(a:file, a:line_nr)
|
|
unlet g:line_map[a:file][a:line_nr]
|
|
unlet g:sign_map[a:file][bookmark['sign_idx']]
|
|
if empty(g:line_map[a:file])
|
|
unlet g:line_map[a:file]
|
|
unlet g:sign_map[a:file]
|
|
endif
|
|
endfunction
|
|
|
|
function! bm#total_count()
|
|
return len(bm#location_list())
|
|
endfunction
|
|
|
|
function! bm#all_bookmarks_by_line(file)
|
|
if !has_key(g:line_map, a:file)
|
|
return {}
|
|
endif
|
|
return g:line_map[a:file]
|
|
endfunction
|
|
|
|
function! bm#all_lines(file)
|
|
if !has_key(g:line_map, a:file)
|
|
return []
|
|
endif
|
|
return keys(g:line_map[a:file])
|
|
endfunction
|
|
|
|
function! bm#location_list()
|
|
let files = sort(bm#all_files())
|
|
let locations = []
|
|
for file in files
|
|
let line_nrs = sort(bm#all_lines(file), "bm#compare_lines")
|
|
for line_nr in line_nrs
|
|
let bookmark = bm#get_bookmark_by_line(file, line_nr)
|
|
let content = bookmark['annotation'] !=# ''
|
|
\ ? "Annotation: ". bookmark['annotation']
|
|
\ : (bookmark['content'] !=# ""
|
|
\ ? bookmark['content']
|
|
\ : "empty line")
|
|
call add(locations, file .":". line_nr .":". content)
|
|
endfor
|
|
endfor
|
|
return locations
|
|
endfunction
|
|
|
|
function! bm#all_files()
|
|
return keys(g:line_map)
|
|
endfunction
|
|
|
|
function! bm#del_all()
|
|
for file in bm#all_files()
|
|
for line_nr in bm#all_lines(file)
|
|
call bm#del_bookmark_at_line(file, line_nr)
|
|
endfor
|
|
endfor
|
|
endfunction
|
|
|
|
function! bm#serialize()
|
|
let file_version = "let l:bm_file_version = 1"
|
|
let sessions = "let l:bm_sessions = {'default': {"
|
|
for file in bm#all_files()
|
|
let sessions .= "'". file ."': ["
|
|
for bm in values(bm#all_bookmarks_by_line(file))
|
|
let escaped_content = substitute(bm['content'], "'", "''", "g")
|
|
let escaped_annotation = substitute(bm['annotation'], "'", "''", "g")
|
|
let annotation = bm['annotation'] !=# "" ? ", 'annotation': '". escaped_annotation ."'" : ""
|
|
let sessions .= "{'sign_idx': ". bm['sign_idx'] .", 'line_nr': ". bm['line_nr'] .", 'content': '". escaped_content ."'". annotation ."},"
|
|
endfor
|
|
let sessions .= "],"
|
|
endfor
|
|
let sessions .= "}}"
|
|
let current_session = "let l:bm_current_session = 'default'"
|
|
return [file_version, sessions, current_session]
|
|
endfunction
|
|
|
|
function! bm#deserialize(data)
|
|
exec join(a:data, " | ")
|
|
let ses = l:bm_sessions["default"]
|
|
let result = []
|
|
for file in keys(ses)
|
|
for bm in ses[file]
|
|
let annotation = has_key(bm, 'annotation') ? bm['annotation'] : ''
|
|
call add(result,
|
|
\ extend(
|
|
\ copy(
|
|
\ bm#add_bookmark(file, bm['sign_idx'], bm['line_nr'], bm['content'], annotation)
|
|
\ ),
|
|
\ {'file': file}
|
|
\ ))
|
|
endfor
|
|
endfor
|
|
return result
|
|
endfunction
|
|
|
|
" }}}
|
|
|
|
|
|
" Private {{{
|
|
|
|
function! bm#compare_lines(line_str1, line_str2)
|
|
let line1 = str2nr(a:line_str1)
|
|
let line2 = str2nr(a:line_str2)
|
|
return line1 ==# line2 ? 0 : line1 > line2 ? 1 : -1
|
|
endfunc
|
|
|
|
" }}}
|