Browse Source

init

master
Gregory Leeman 3 years ago
commit
dff977f50d
  1. 5
      README.md
  2. 363
      autoload/notecrate.vim
  3. 34
      ftplugin/notecrate.vim
  4. 9
      plugin/notecrate.vim
  5. 37
      syntax/notecrate.vim

5
README.md

@ -0,0 +1,5 @@
# notecrate
## Requirements

363
autoload/notecrate.vim

@ -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
" }}}

34
ftplugin/notecrate.vim

@ -0,0 +1,34 @@
setlocal textwidth=79
setlocal autowriteall
setlocal comments+=b:*
setlocal foldlevel=3
setlocal formatoptions=cro
command! SearchOpen :call notecrate#base#search_open()
command! SearchInsertLink :call notecrate#base#search_insert_link()
command! UpdateBacklinks :call notecrate#base#update_backlinks()
command! NewNote :call notecrate#base#new_note_from_prompt()
command! DeleteNote :call notecrate#base#delete_note()
command! Convert :call notecrate#base#convert()
command! Save :call notecrate#base#save()
" inoremap <buffer> <Esc> <Esc>mmgqis`m
nnoremap <buffer> <leader>c :Convert<CR>
nnoremap <buffer> <leader>o :SearchOpen<CR>
nnoremap <buffer> <leader>i :SearchInsertLink<CR>
nnoremap <buffer> <leader>b :UpdateBacklinks<CR>
nnoremap <buffer> <leader>n :NewNote<CR>
nnoremap <buffer> <leader>d :DeleteNote<CR>
nnoremap <buffer> <leader>s :Convert<CR>:Save<CR>
nnoremap <buffer> <CR> :call notecrate#base#follow_link()<CR>
vnoremap <buffer> <CR> :call notecrate#base#new_note_from_selection()<CR>
nnoremap <buffer> <backspace> :call notecrate#base#open_previous()<CR>
nnoremap <buffer> <S-j> /\[[^\]]*\]([^)]*)<CR>:noh<CR>
nnoremap <buffer> <S-l> /\[[^\]]*\]([^)]*)<CR>:noh<CR>
nnoremap <buffer> <Tab> /\[[^\]]*\]([^)]*)<CR>:noh<CR>
nnoremap <buffer> <S-Tab> /\[[^\]]*\]([^)]*)<CR>NN:noh<CR>
nnoremap <buffer> <S-h> /\[[^\]]*\]([^)]*)<CR>NN:noh<CR>
nnoremap <buffer> <S-k> /\[[^\]]*\]([^)]*)<CR>NN:noh<CR>
vnoremap <buffer> <leader>i :call notecrate#base#search_insert_link_selection()<CR>
inoremap <buffer> <Tab> <C-t>
inoremap <buffer> <S-Tab> <C-d>

9
plugin/notecrate.vim

@ -0,0 +1,9 @@
if !exists("g:notecrate_dirs")
let g:notecrate_dirs = {
\ "notes": { "prefix": "n", "dir": "~/notecrate"}
\ }
endif
for [key, value] in items(g:notecrate_dirs)
execute "autocmd BufRead,BufNewFile " . value["dir"] . "/*.md set filetype=notecrate syntax=notecrate"
execute "normal! :nnoremap <leader>w" . value["prefix"] . " :e " . value["dir"] . "/index.md<CR>:let b:notecrate_dir = \"" . value["dir"] . "\"<CR>:let b:notecrate_history = []<CR>\<CR>"
endfor

37
syntax/notecrate.vim

@ -0,0 +1,37 @@
setlocal foldmethod=expr
setlocal foldexpr=notecrate#base#nested_markdown_folds(v:lnum)
setlocal foldtext=notecrate#base#fold_text()
setlocal conceallevel=2
set comments=b:*
setlocal nowrap
syn match NotecrateLinkInternal /\(\](\)\@<=[^()]*\()\)\@=/
syn match NotecrateLinkConceal /!*\[\+\([^\]]*](\)\@=/ conceal
syn match NotecrateLinkConceal /\]\+\((\)\@=/ conceal
syn match NotecrateLinkConceal /\(\[[^\]]*\]\)\@<=([^)]*)/ conceal contains=NotecrateLinkInternal
syn match NotecrateLink /\(\[\)\@<=[^\[\]]*\(\](\)\@=/
syn match NotecrateLinkImage /\(!\[\+\)\@<=[^\[\]]*\(\]\+\)\@=/
syn match NotecrateHeader1 /\(^# \)\@<=.*/
syn match NotecrateHeader2 /\(^##\+ \)\@<=.*/
syn match NotecrateRule /^---\+/
syn region NotecrateFrontCustomMatter start=/\%^---/ end=/^---/
syn region NotecrateCode start=/^```/ end=/^```/
" syn match NotecrateBoldConceal /\*\*/ conceal containedin=ALL
syn match NotecrateBoldConceal /\*\*/ containedin=ALL
syn region NotecrateBold start=/\*\*/ end=/\*\*/ contains=NotecrateBoldConceal keepend
syn match NotecrateQuote /^>.*$/
syn match NotecrateTag /#[^# ]\S*/
hi def link NotecrateBold base2
hi def link NotecrateTag cyanu
hi def link NotecrateCode red
hi def link NotecrateFrontCustomMatter base01
hi def link NotecrateHeader1 base3u
hi def link NotecrateHeader2 base1u
hi def link NotecrateLink blueu
hi def link NotecrateLinkConceal blue
hi def link NotecrateLinkImage redu
hi def link NotecrateLinkInternal orangeu
hi def link NotecrateList base2
hi def link NotecrateQuote cyan
hi def link NotecrateRule base01