|
|
@ -0,0 +1,363 @@ |
|
|
|
function! notecrate#get_visual_selection() " {{{ |
|
|
|
let [line_start, column_start] = getpos("'<")[1:2] |
|
|
|
let [line_end, column_end] = getpos("'>")[1:2] |
|
|
|
let lines = getline(line_start, line_end) |
|
|
|
if len(lines) == 0 |
|
|
|
return '' |
|
|
|
endif |
|
|
|
let lines[-1] = lines[-1][: column_end - (&selection == 'inclusive' ? 1 : 2)] |
|
|
|
let lines[0] = lines[0][column_start - 1:] |
|
|
|
return join(lines, "\n") |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#get_word_at_cursor() " {{{ |
|
|
|
let l:word = expand('<cWORD>') |
|
|
|
return l:word |
|
|
|
endfunction |
|
|
|
" }}} |
|
|
|
function! notecrate#get_link_at_cursor() " {{{ |
|
|
|
let l:regex = '\[\([^\]]*\)\](\([^)]*\))' |
|
|
|
let l:line = getline('.') |
|
|
|
let l:cursor = col('.') - 1 |
|
|
|
let l:match = matchstrpos(l:line, l:regex, 0) |
|
|
|
while 1 |
|
|
|
if (l:match[1] == -1) |
|
|
|
return '' |
|
|
|
elseif l:match[1] <= l:cursor && l:cursor < l:match[2] |
|
|
|
break |
|
|
|
endif |
|
|
|
let l:match = matchstrpos(l:line, l:regex, l:match[2] + 1) |
|
|
|
endwhile |
|
|
|
let l:matches = matchlist(l:match[0], l:regex) |
|
|
|
return {'text': l:matches[1], 'dest': l:matches[2]} |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#generate_filename() " {{{ |
|
|
|
return strftime("%Y%m%d%H%M%S") . ".md" |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#apply_template(title) " {{{ |
|
|
|
let l:template = "# " . a:title . "\n\n\n---\n\n" |
|
|
|
call setreg("l", l:template) |
|
|
|
silent execute 'normal "lP4j' |
|
|
|
call notecrate#update_backlinks() |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#convert() " {{{ |
|
|
|
execute "normal! :w!\<CR>:!pushd " . b:notecrate_dir . "; bash convert.sh;\<CR>" |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#save() " {{{ |
|
|
|
execute "normal! :!cd " . b:notecrate_dir . "; git add -A; git commit -m \"autocommit\"; git push;\<CR>" |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#todo_filter_view() " {{{ |
|
|
|
execute "normal! :!cd " . b:notecrate_dir . "; git add -A; git commit -m \"autocommit\"; git push;\<CR>" |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#follow_link() " {{{ |
|
|
|
let l:link = notecrate#get_link_at_cursor()" |
|
|
|
if type(l:link) == 4 |
|
|
|
if l:link['dest'] =~ '^.*\.md$' |
|
|
|
call notecrate#open_note(l:link['dest']) |
|
|
|
else |
|
|
|
silent execute "open " . l:link['dest'] |
|
|
|
endif |
|
|
|
endif |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#new_note(title, filename) " {{{ |
|
|
|
let l:filename = expand('%:t') |
|
|
|
while !isdirectory(expand(b:notecrate_dir)) |
|
|
|
let choice = confirm('', b:notecrate_dir . " does not exist. Create? &Yes\n&No\n") |
|
|
|
if choice == 1 |
|
|
|
silent execute "!mkdir " . b:notecrate_dir |
|
|
|
else |
|
|
|
return 0 |
|
|
|
endif |
|
|
|
endwhile |
|
|
|
let l:path = b:notecrate_dir . "/" . a:filename |
|
|
|
call add(b:notecrate_history, l:filename) |
|
|
|
silent execute "normal! :w\<CR>:e " . l:path . "\<CR>" |
|
|
|
call notecrate#apply_template(a:title) |
|
|
|
call notecrate#update_backlinks() |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#new_note_from_prompt() " {{{ |
|
|
|
let l:title = input("Name of new note? ") |
|
|
|
let l:filename = notecrate#generate_filename() |
|
|
|
call notecrate#new_note(l:title, l:filename) |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#new_note_from_selection() " {{{ |
|
|
|
let l:title = notecrate#get_visual_selection() |
|
|
|
let l:filename = notecrate#generate_filename() |
|
|
|
silent execute "normal! :'<,'>s/\\%V.*\\%V/[" . l:title . "](" . l:filename . ")/e\<CR>" |
|
|
|
call notecrate#new_note(l:title, l:filename) |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#open_note(filename) " {{{ |
|
|
|
let l:filename = expand('%:t') |
|
|
|
let l:path = b:notecrate_dir . "/" . a:filename |
|
|
|
if !filereadable(expand(l:path)) |
|
|
|
echo "Note does't exist!" |
|
|
|
return |
|
|
|
endif |
|
|
|
call add(b:notecrate_history, l:filename) |
|
|
|
silent execute "e " . l:path |
|
|
|
call notecrate#update_backlinks() |
|
|
|
silent execute "normal! /^#\<CR>" |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#open_index() " {{{ |
|
|
|
while !isdirectory(expand(b:notecrate_dir)) |
|
|
|
let choice = confirm('', b:notecrate_dir . " does not exist. Create? &Yes\n&No\n") |
|
|
|
if choice == 1 |
|
|
|
silent execute "!mkdir " . b:notecrate_dir |
|
|
|
else |
|
|
|
return 0 |
|
|
|
endif |
|
|
|
endwhile |
|
|
|
let l:filename = "index.md" |
|
|
|
let l:path = b:notecrate_dir . "/" . l:filename |
|
|
|
if !filereadable(expand(l:path)) |
|
|
|
echo "Note does't exist!" |
|
|
|
return |
|
|
|
endif |
|
|
|
silent execute "e " . l:path |
|
|
|
call notecrate#update_backlinks() |
|
|
|
silent execute "normal! /^#\<CR>" |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#open_previous() " {{{ |
|
|
|
if len(b:notecrate_history) == 0 |
|
|
|
return |
|
|
|
endif |
|
|
|
let l:filename = remove(b:notecrate_history, -1) |
|
|
|
call notecrate#open_note(l:filename) |
|
|
|
call remove(b:notecrate_history, -1) |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#get_title(filename) " {{{ |
|
|
|
let l:regex = '^# \(\S.*\)$' |
|
|
|
let l:path = b:notecrate_dir . "/" . a:filename |
|
|
|
let l:lines = readfile(expand(l:path)) |
|
|
|
let l:line = matchstr(l:lines, l:regex) |
|
|
|
if l:line != "" |
|
|
|
return matchlist(l:line, l:regex)[1] |
|
|
|
endif |
|
|
|
return '' |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#get_id(filename) " {{{ |
|
|
|
return = matchstr(a:filename, '^.*\(\.md$\)\@=') |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#fzf_sink(sink_function) " {{{ |
|
|
|
" let l:additional_options = get(a:, 1, {}) |
|
|
|
let l:preview_options = { |
|
|
|
\ 'sink' : function(a:sink_function), |
|
|
|
\ 'down' : '~40%', |
|
|
|
\ 'dir' : b:notecrate_dir, |
|
|
|
\ 'options' : ['--exact', '--tiebreak=end'] |
|
|
|
\ } |
|
|
|
" call fzf#vim#ag("^(?=.)", fzf#vim#with_preview(l:preview_options)) |
|
|
|
call fzf#vim#ag("^# ", fzf#vim#with_preview(l:preview_options)) |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#search_open() " {{{ |
|
|
|
call notecrate#fzf_sink('notecrate#open_from_fzf') |
|
|
|
endfunction |
|
|
|
function! notecrate#open_from_fzf(line) |
|
|
|
let filename = substitute(a:line, ":[0-9]\*:[0-9]\*:.\*$", "", "") |
|
|
|
call notecrate#open_note(filename) |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#search_insert_link() " {{{ |
|
|
|
call notecrate#fzf_sink('notecrate#insert_link_from_fzf') |
|
|
|
endfunction |
|
|
|
function! notecrate#insert_link_from_fzf(line) |
|
|
|
let l:filename = substitute(a:line, ":[0-9]\*:[0-9]\*:.\*$", "", "") |
|
|
|
let l:title = notecrate#get_title(filename) |
|
|
|
execute "normal! a[" . l:title . "](" . l:filename . ")\<Esc>" |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#search_insert_link_selection() " {{{ |
|
|
|
call notecrate#fzf_sink('notecrate#insert_link_from_fzf_selection') |
|
|
|
endfunction |
|
|
|
function! notecrate#insert_link_from_fzf_selection(line) |
|
|
|
let l:filename = substitute(a:line, ":[0-9]\*:[0-9]\*:.\*$", "", "") |
|
|
|
let l:title = notecrate#get_visual_selection() |
|
|
|
silent execute "normal! :'<,'>s/\\%V.*\\%V/[" . l:title . "](" . l:filename . ")/e\<CR>" |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#grep(pattern) " {{{ |
|
|
|
let l:files = [] |
|
|
|
try |
|
|
|
silent execute 'vimgrep /' . a:pattern . '/j ' . b:notecrate_dir . '/*.md' |
|
|
|
catch /^Vim\%((\a\+)\)\=:E480/ " No Match |
|
|
|
endtry |
|
|
|
for d in getqflist() |
|
|
|
let l:filename = fnamemodify(bufname(d.bufnr), ":t") |
|
|
|
call add(l:files, l:filename) |
|
|
|
endfor |
|
|
|
call uniq(l:files) |
|
|
|
return l:files |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#grep_links(pattern) " {{{ |
|
|
|
let l:files = notecrate#grep(a:pattern) |
|
|
|
let l:links = [] |
|
|
|
for filename in l:files |
|
|
|
if filename != "index.md" |
|
|
|
let l:title = notecrate#get_title(filename) |
|
|
|
call add(l:links, "* [" . l:title . "](" . filename . ")") |
|
|
|
endif |
|
|
|
endfor |
|
|
|
return sort(l:links) |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#update_backlinks() " {{{ |
|
|
|
let l:filename = expand('%:t') |
|
|
|
if l:filename == "index.md" |
|
|
|
return |
|
|
|
endif |
|
|
|
let l:pattern = '\[[^\]]*\](' . l:filename . ')\(\(.*\n\)*---\)\@=' |
|
|
|
let l:links = notecrate#grep_links(l:pattern) |
|
|
|
let l:backlinks = "---\n\n" |
|
|
|
if len(l:links) == 0 |
|
|
|
let l:backlinks = l:backlinks . "* [Index](index.md)" |
|
|
|
else |
|
|
|
let l:backlinks = l:backlinks . join(uniq(l:links), "\n") . "\n\n* [Index](index.md)" |
|
|
|
endif |
|
|
|
let l:oldreg = getreg("0") |
|
|
|
call setreg("l", l:backlinks) |
|
|
|
silent execute "normal! /^---\<CR>vG$\"lp" |
|
|
|
call setreg("0", l:oldreg) |
|
|
|
call setreg("", l:oldreg) |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#delete_links(filename) " {{{ |
|
|
|
execute "!" . g:gsed_command . " -i 's/\\[\\([^]]*\\)\\](" . a:filename . ")/\\1/g' " . b:notecrate_dir . "/*md" |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#delete_note() " {{{ |
|
|
|
let l:filename = expand('%:t') |
|
|
|
let l:path = b:notecrate_dir . "/" . l:filename |
|
|
|
let choice = confirm('', "Delete " . l:filename . "? &Yes\n&No\n") |
|
|
|
if choice == 1 |
|
|
|
call delete(l:path) |
|
|
|
call notecrate#delete_links(l:filename) |
|
|
|
silent execute "!rm " l:path |
|
|
|
silent execute "normal :bp!\<CR>" |
|
|
|
endif |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#indent_level(lnum) " {{{ |
|
|
|
return indent(a:lnum) / &shiftwidth |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#heading_depth(lnum) " {{{ |
|
|
|
let l:depth=0 |
|
|
|
let l:thisLine = getline(a:lnum) |
|
|
|
if l:thisLine =~ '^#\+\s\+' |
|
|
|
let l:hashCount = len(matchstr(thisLine, '^#\{1,6}')) |
|
|
|
if l:hashCount > 0 |
|
|
|
let l:depth = hashCount - 1 |
|
|
|
endif |
|
|
|
elseif l:thisLine != '' |
|
|
|
let l:nextLine = getline(a:lnum + 1) |
|
|
|
if l:nextLine =~ '^=\+\s*$' |
|
|
|
let l:depth = 1 |
|
|
|
elseif l:nextLine =~ '^-\+\s*$' |
|
|
|
let l:depth = 2 |
|
|
|
endif |
|
|
|
endif |
|
|
|
return l:depth |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#nested_markdown_folds(lnum) " {{{ |
|
|
|
let l:thisLine = getline(a:lnum) |
|
|
|
let l:thisDepth = notecrate#heading_depth(a:lnum) |
|
|
|
let l:thisIndent = notecrate#indent_level(a:lnum) |
|
|
|
let l:prevLine = getline(a:lnum - 1) |
|
|
|
let l:prevIndent = notecrate#indent_level(a:lnum - 1) |
|
|
|
let l:nextLine = getline(a:lnum + 1) |
|
|
|
let l:nextIndent = notecrate#indent_level(a:lnum + 1) |
|
|
|
let l:nextDepth = notecrate#heading_depth(a:lnum + 1) |
|
|
|
|
|
|
|
if l:thisLine =~ '^\s*<' && l:prevLine =~ '^\s*$' |
|
|
|
return 1 |
|
|
|
endif |
|
|
|
|
|
|
|
if l:thisLine =~ '^\s*$' && l:prevLine =~ '^\s*<' |
|
|
|
return 0 |
|
|
|
endif |
|
|
|
|
|
|
|
if l:nextLine =~ '^---$' || l:thisLine =~ '^---$' |
|
|
|
return 0 |
|
|
|
endif |
|
|
|
|
|
|
|
if l:thisLine =~ '^\s*$' && l:nextDepth > 0 |
|
|
|
return -1 |
|
|
|
endif |
|
|
|
|
|
|
|
if l:thisDepth > 0 |
|
|
|
return ">".l:thisDepth |
|
|
|
endif |
|
|
|
|
|
|
|
if l:nextIndent == l:thisIndent |
|
|
|
return "=" |
|
|
|
endif |
|
|
|
|
|
|
|
if l:nextIndent > l:thisIndent |
|
|
|
let l:dif = l:nextIndent - l:thisIndent |
|
|
|
return "a".l:dif |
|
|
|
endif |
|
|
|
|
|
|
|
if l:nextIndent < l:thisIndent |
|
|
|
let l:dif = l:thisIndent - l:nextIndent |
|
|
|
return "s".l:dif |
|
|
|
endif |
|
|
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |
|
|
|
function! notecrate#fold_text() " {{{ |
|
|
|
if getline(v:foldstart) =~ "^\s*<" |
|
|
|
return "<>" . repeat(" ", winwidth(0)) |
|
|
|
endif |
|
|
|
let l:ret = repeat(" ", indent(v:foldstart)) . trim(getline(v:foldstart))[0:-1] . " +" . repeat(" ", winwidth(0)) |
|
|
|
let l:ret = substitute(l:ret, ' \S\+:\S\+', '', 'g') |
|
|
|
let l:ret = substitute(l:ret, '\*\*', '', 'g') |
|
|
|
return l:ret |
|
|
|
endfunction |
|
|
|
|
|
|
|
" }}} |