" Global configurations {{{1 " List of denote directories: if !exists('g:denote_directories') let g:denote_directories=[] endif call map(g:denote_directories, {_, d -> fnamemodify(d, ':p')}) " If only one directory has been specified, use that as denote directory if ! empty(g:denote_directories) let t:denote_directory = g:denote_directories[0] endif " Restrict basic operations to these files: if !exists('g:denote_note_file_extensions') let g:denote_note_file_extensions=['md', 'org', 'txt'] endif " Number of columns used for the title in the location window. if !exists('g:denote_loc_title_columns') let g:denote_loc_title_columns=40 endif " Default filetype for newly created denote entries if !exists('g:denote_new_ft') let g:denote_new_ft='md' endif " Default front-matter type for markdown notes, may be one of 'yaml' or 'toml' if !exists('g:denote_fm_md_type') let g:denote_fm_md_type='yaml' endif " By using the following global variable, the user may specify a custom " function for creating identifiers. if !exists('g:denote_identifier_fun') let g:denote_identifier_fun='' endif " Local functions {{{1 " Put all notes of the given tag to the location list. The tag argument is " mandatory. function s:DenoteNotesByTag(tag) if !exists('t:denote_directory') echohl WarningMsg echom "Denote directory not specified, see |vim-denote|." return endif " Clear location list call denote#loclist#clear() " Find files let files = glob(t:denote_directory .. "*_" .. a:tag .. "*", 0, v:true)->filter('v:val =~ "_' .. a:tag .. '\\(==\\|@@\\|__\\|_\\|\\.\\)"') " Populate location list let locTitle="Denote notes: " .. a:tag call setloclist(0, [], 'r', \ {'title': locTitle, \ 'quickfixtextfunc' : 'denote#loclist#textNoteList'}) let notes=[] for f in files call add(notes, { \ 'filename' : f, \ 'lnum' : 1 \ }) endfor call setloclist(0, notes, 'a') endfunction " Put all notes of the given tag to the location list. The search argument may be " empty. For improving search, white spaces are replaced by the * |wildcard|. function s:DenoteNotes(search) if !exists('t:denote_directory') echohl WarningMsg echom "Denote directory not specified, see |vim-denote|." return endif let s = substitute(" " .. a:search .. " ", " ", "*", "g") " Clear location list call denote#loclist#clear() " Find files let files = glob(t:denote_directory .. s, 0, v:true) " Populate location list let locTitle="Denote notes search:" .. a:search call setloclist(0, [], 'r', \ {'title': locTitle, \ 'quickfixtextfunc' : 'denote#loclist#textNoteList'}) let notes=[] for f in files call add(notes, { \ 'filename' : f, \ 'lnum' : 1 \ }) endfor call setloclist(0, notes, 'a') endfunction " This function implements the similar functionality of :vimgrep, but for " denote notes. function s:DenoteGrep(search) if !exists('t:denote_directory') echohl WarningMsg echom "Denote directory not specified, see |vim-denote|." return endif " Clear location list call denote#loclist#clear() " Grep all greppable files let fpat=map(copy(g:denote_note_file_extensions), {_, e -> t:denote_directory .. "*." .. e})->join() execute "silent! lvimgrep " .. a:search .. " " .. fpat " Adjust location list: set title and specify display function call setloclist(0, [], 'r', \ {'title': 'Denote grep: ' .. a:search, \ 'quickfixtextfunc' : 'denote#loclist#textReferences'}) lclose lopen endfunction " This function is used to autocomplete the tags in user commands. function s:tagList(ArgLead, cmdLine, CursorPos) let files=glob(t:denote_directory .. "*", 0, v:true) let tags=[] for f in files let tags=extend(tags, denote#meta#noteTagsFromFile(f)) endfor return uniq(sort(tags))->join("\n") endfunction " This creates a new denote entry with the given title and of the given " filetype. The title may be empty. function s:DenoteNew(title, ft=g:denote_new_ft) if !exists('t:denote_directory') echohl WarningMsg echom "Denote directory not specified, see |vim-denote|." return endif let identifier=denote#meta#identifier_generate() let fn=identifier .. '--' .. a:title \ ->tolower() \ ->substitute('[^[:fname:]]\|/', '-', 'g') \ ->substitute('-\+', '-', 'g') \ ->trim('-') .. '.' .. a:ft execute "edit " .. t:denote_directory .. fn call setline(1, denote#frontmatter#new(a:ft, identifier, a:title)) endfunction " Transform full path into canonical form WITH trailing '/' function s:canonicalFullPath(path) let parts = split(a:path, '/') let result = [] for part in parts if part == '.' || part == '' continue elseif part == '..' if len(result) > 0 call remove(result, len(result)-1) endif else call add(result, part) endif endfor return empty(result) ? '/' : '/' .. join(result, '/') .. '/' endfunction " Compute the relative path from start to target. Both arguments are given as " full paths. function s:relativePath(start, target) let a = s:canonicalFullPath(a:start) let b = s:canonicalFullPath(a:target) " Simple cases first: both paths are the same, or the target is a subpath " from the start. if a == b[:strlen(a)-1] return b[strlen(a):] endif " Now, we need to go back. If the following match fails, then we need to go " back all the way let l = matchstrpos(a .. b, '^\(/.*\)/\zs.*/\ze\1') return l[1] == -1 \ ? substitute(a[1:-2], '[^/]\+', '..', 'g') .. b \ : substitute(l[0], '[^/]\+', '..', 'g') .. b[l[1]:] endfunction " Complete all paths to the denote directories. This functions completes the " paths to the configured directories, TODO: but also shows the directories " accessible from the current position. function s:denoteDirectoryList(ArgLead, CmdLine, CursorPos) let prefix = fnamemodify(a:ArgLead ?? '/', ':p') let res = [] for dendir in g:denote_directories if prefix == dendir[:strlen(prefix)-1] call add(res, substitute(a:ArgLead .. '/' .. s:relativePath(prefix, dendir), '/\+', '/', 'g')) endif endfor " TODO: Append all subdirectories (default directory completion) return res->join("\n") endfunction " Public commands and key mappings {{{1 command -nargs=1 -complete=custom,denoteDirectoryList Denote let t:denote_directory = fnamemodify(, ':p') command -nargs=* DenoteSearch call DenoteNotes() command -nargs=1 -complete=custom,tagList DenoteTag call DenoteNotesByTag() command -nargs=+ DenoteGrep call DenoteGrep() command -nargs=1 DenoteNew call DenoteNew() " Useful key mappings nnoremap DenoteList :DenoteSearch:lclose:lopen:resize 20 nnoremap DenoteBackReferences :DenoteBackReferences:lclose:lopen:resize 20