Files
vim-denote/plugin/denote.vim
2026-02-25 15:32:05 +01:00

120 lines
3.7 KiB
VimL

" Global configurations
" 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 len(g:denote_directories) == 1
" let g: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
" Transform full path into canonical form WITH trailing '/'
function s:canonicalFullPath(path)
let l:parts = split(a:path, '/')
let l:result = []
for part in l:parts
if part == '.' || part == ''
continue
elseif part == '..'
if len(l:result) > 0
call remove(l:result, len(l:result)-1)
endif
else
call add(l:result, part)
endif
endfor
return empty(l:result) ? '/' : '/' .. join(l:result, '/') .. '/'
endfunction
" Compute the relative path from start to target. Both arguments are given as
" full paths.
function s:relativePath(start, target)
let l:a = s:canonicalFullPath(a:start)
let l:b = s:canonicalFullPath(a:target)
" Simple cases first: both paths are the same, or the target is l:a subpath
" from the start.
if l:a == l:b[:strlen(l:a)-1]
return l:b[strlen(l:a):]
endif
" Now, we need to go back. If the following match fails, then we need to go
" back all the way
let l:l = matchstrpos(l:a .. l:b, '^\(/.*\)/\zs.*/\ze\1')
return l:l[1] == -1
\ ? substitute(l:a[1:-2], '[^/]\+', '..', 'g') .. l:b
\ : substitute(l:l[0], '[^/]\+', '..', 'g') .. l:b[l:l[1]:]
endfunction
" Complete all paths to the denote directories. This functions completes the
" paths to the configured directories.
function s:denoteDirectoryCompletion(ArgLead, CmdLine, CursorPos)
let l:res = []
let l:bang = match(a:CmdLine, '^\S\+!') >= 0
let l:argleaddir = isdirectory(expand(a:ArgLead)) ? a:ArgLead : matchstr(a:ArgLead, '^.*/')
if strlen(l:argleaddir) == 0
let l:argleaddir = '~'
endif
if l:argleaddir !~ '/$'
let l:argleaddir = l:argleaddir .. '/'
endif
if l:bang
for ldir in (glob(expand(l:argleaddir) .. '/*', v:true, v:true)->filter('isdirectory(v:val)'))
call add(l:res, l:argleaddir .. fnamemodify(ldir, ':t'))
endfor
else
let l:leaddir = s:canonicalFullPath(fnamemodify(l:argleaddir, ':p'))
for ldir in g:denote_directories
if l:leaddir == ldir[:strlen(l:leaddir)-1]
call add(l:res, l:argleaddir .. s:relativePath(l:leaddir, ldir))
endif
endfor
endif
return l:res->join("\n")
endfunction
" Setup denote plugin, i.e.,
" - set the denote directory
" - register user commands
" - register auto commands
function s:setup(dir)
" Set the denote directory
let l:tmp = s:canonicalFullPath(fnamemodify(a:dir, ':p'))[:-2]
if !isdirectory(l:tmp)
echohl WarningMsg
echom "The specified argument is not a directory (" .. a:dir .. ")"
return
endif
let g:denote_directory = l:tmp
" Register user commands and auto commands
call denote#commands#load()
endfunction
command -nargs=1 -bang -complete=custom,s:denoteDirectoryCompletion DenoteDirectory call s:setup(<f-args>)