From 21e65cf4da7cce7eeefa81cca89162d28b816047 Mon Sep 17 00:00:00 2001 From: EinfachToll Date: Mon, 30 Apr 2018 21:27:00 +0200 Subject: [PATCH] Unify path handling -- part 5 --- autoload/vimwiki/base.vim | 2 +- autoload/vimwiki/html.vim | 287 +++++++++++++++++--------------------- autoload/vimwiki/path.vim | 38 ++++- ftplugin/vimwiki.vim | 15 +- 4 files changed, 169 insertions(+), 173 deletions(-) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index 530dba3..971bfae 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -121,7 +121,7 @@ function! vimwiki#base#resolve_link(link_text, ...) let link_infos = { \ 'index': -1, \ 'scheme': '', - \ 'filename': '', + \ 'filename': '', " XXX das sollte file heißen und ein file_obj ergeben. Was passiert bei http://bla.blubb? \ 'anchor': '', \ } diff --git a/autoload/vimwiki/html.vim b/autoload/vimwiki/html.vim index d808e65..b4c3269 100644 --- a/autoload/vimwiki/html.vim +++ b/autoload/vimwiki/html.vim @@ -10,8 +10,8 @@ endif let g:loaded_vimwiki_html_auto = 1 -function! s:root_path(subdir) - return vimwiki#path#relpath(vimwiki#vars#get_wikilocal('path'), a:subdir) +function! s:path_from_subdir_to_root(subdir) + return vimwiki#path#relpath(a:subdir, vimwiki#vars#get_wikilocal('path_html')) endfunction @@ -43,14 +43,31 @@ function! s:is_img_link(lnk) endfunction -function! s:default_CSS_full_name(path) - return vimwiki#path#join(a:path, vimwiki#vars#get_wikilocal('css_name')) +function! s:corresponding_html_file(wiki_file) + let relative_wiki_path = vimwiki#path#subtract(vimwiki#vars#get_wikilocal('path'), a:wiki_file) + let html_file = vimwiki#path#join(vimwiki#vars#get_wikilocal('path_html'), relative_wiki_path) + let html_file = vimwiki#path#set_extension(html_file, 'html') + return html_file +endfunction + + +function! s:corresponding_wiki_file(html_file) + let html_path = vimwiki#path#subtract(vimwiki#vars#get_wikilocal('path_html'), a:html_file) + let wiki_file = vimwiki#path#join(vimwiki#vars#get_wikilocal('path'), html_path) + let wiki_file = vimwiki#path#set_extension(wiki_file, vimwiki#vars#get_wikilocal('ext')) + return wiki_file +endfunction + + +function! s:default_CSS_full_name() + return vimwiki#path#join(vimwiki#vars#get_wikilocal('path_html'), + \ vimwiki#vars#get_wikilocal('css_name')) endfunction " Returns: 1 if it was created, 0 if it already existed -function! s:create_default_CSS(target_dir) - let css_full_name = s:default_CSS_full_name(a:target_dir) +function! s:create_default_CSS() + let css_full_name = s:default_CSS_full_name() if vimwiki#path#exists(css_full_name) return 0 else @@ -62,46 +79,31 @@ endfunction function! s:template_full_name(name) - if a:name == '' - let name = vimwiki#vars#get_wikilocal('template_default') - else - let name = a:name - endif - let filename = vimwiki#path#file_segment(name . vimwiki#vars#get_wikilocal('template_ext')) - - let template_file = vimwiki#path#to_string(vimwiki#path#join(vimwiki#vars#get_wikilocal('template_path'), filename)) - - if filereadable(template_file) - return template_file - else - return '' - endif + let template_file = vimwiki#path#join(vimwiki#vars#get_wikilocal('template_path'), filename) + return template_file endfunction -function! s:get_html_template(template) - " TODO: refactor it!!! - let lines=[] - - if a:template != '' - let template_name = s:template_full_name(a:template) +function! s:get_html_template(template_name) + if a:template_name != '' + let template_file = s:template_full_name(a:template) try - let lines = readfile(template_name) + let lines = readfile(vimwiki#path#to_string(template_file)) return lines catch /E484/ - echomsg 'Vimwiki: HTML template '.template_name. ' does not exist!' + echomsg 'Vimwiki: HTML template '.vimwiki#path#to_string(template_file). ' does not exist!' endtry + return [] + else + let default_template_file = + \ s:template_full_name(vimwiki#vars#get_wikilocal('template_default')) + if !vimwiki#path#exists(default_template_file) + let default_template_file = vimwiki#path#find_autoload_file('default.tpl') + endif + let lines = readfile(default_tpl) + return lines endif - - let default_tpl = s:template_full_name('') - - if default_tpl == '' - let default_tpl = vimwiki#path#to_string(vimwiki#path#find_autoload_file('default.tpl')) - endif - - let lines = readfile(default_tpl) - return lines endfunction @@ -129,26 +131,25 @@ function! s:safe_html_line(line) endfunction -function! s:delete_html_files(path) - let htmlfiles = vimwiki#path#files_in_dir_recursive(a:path, 'html') - for fname in htmlfiles +function! s:delete_html_files() + let htmlfiles = + \ vimwiki#path#files_in_dir_recursive(vimwiki#vars#get_wikilocal('path_html'), 'html') + for html_file in htmlfiles + " ignore user html files, e.g. search.html,404.html - if stridx(vimwiki#vars#get_global('user_htmls'), fnamemodify(fname, ":t")) >= 0 + if index(vimwiki#vars#get_global('user_htmls'), vimwiki#path#filename(html_file)) >= 0 continue endif " delete if there is no corresponding wiki file - let subdir = vimwiki#base#subdir(vimwiki#vars#get_wikilocal('path_html'), fname) - let wikifile = vimwiki#vars#get_wikilocal('path').subdir. - \fnamemodify(fname, ":t:r").vimwiki#vars#get_wikilocal('ext') - if filereadable(wikifile) + if vimwiki#path#exists(s:corresponding_wiki_file(html_file)) continue endif try - call delete(fname) + call delete(vimwiki#path#to_string(html_file)) catch - echomsg 'Vimwiki Error: Cannot delete '.fname + echomsg 'Vimwiki Error: Cannot delete '.vimwiki#path#to_string(html_file) endtry endfor endfunction @@ -216,21 +217,15 @@ endfunction function! s:is_html_uptodate(wikifile) - let tpl_time = -1 + let htmlfile_ftime = getftime(vimwiki#path#to_string(s:corresponding_html_file(a:wikifile))) - let tpl_file = s:template_full_name('') - if tpl_file != '' - let tpl_time = getftime(tpl_file) - endif + " The HTML file should also be considered out of date if the default template has been changed in + " the meantime. This is not completely correct, because the wiki file could use a template which + " is not the default one. But it's better than nothing. + let tpl_file = s:template_full_name(vimwiki#vars#get_wikilocal('template_default')) + let tpl_time = getftime(tpl_file) - let wikifile = fnamemodify(a:wikifile, ":p") - let htmlfile = expand(vimwiki#vars#get_wikilocal('path_html') . - \ vimwiki#vars#get_bufferlocal('subdir') . fnamemodify(wikifile, ":t:r").".html") - - if getftime(wikifile) <= getftime(htmlfile) && tpl_time <= getftime(htmlfile) - return 1 - endif - return 0 + return getftime(wikifile) <= htmlfile_ftime && tpl_time <= htmlfile_ftime endfunction @@ -395,17 +390,18 @@ function! s:tag_wikiincl(value) let link_infos = vimwiki#base#resolve_link(url_0) if link_infos.scheme =~# '\mlocal\|wiki\d\+\|diary' - let url = vimwiki#path#relpath(fnamemodify(s:current_html_file, ':h'), link_infos.filename) + let url = vimwiki#path#relpath(vimwiki#path#directory_of_file(s:current_html_file), + \ link_infos.filename) " strip the .html extension when we have wiki links, so that the user can " simply write {{image.png}} to include an image from the wiki directory if link_infos.scheme =~# '\mwiki\d\+\|diary' - let url = fnamemodify(url, ':r') + let url = vimwiki#path#filename_without_extension(url) endif else - let url = link_infos.filename + let url = link_infos.file endif - let url = escape(url, '#') + let url = escape(vimwiki#path#to_string(url), '#') let line = s:linkify_image(url, descr, verbatim_str) endif return line @@ -431,20 +427,17 @@ function! s:tag_wikilink(value) if link_infos.scheme ==# 'file' " external file links are always absolute - let html_link = link_infos.filename + let html_link = vimwiki#path#to_string(link_infos.file) elseif link_infos.scheme ==# 'local' - let html_link = vimwiki#path#relpath(fnamemodify(s:current_html_file, ':h'), - \ link_infos.filename) + let html_link = vimwiki#path#to_string(vimwiki#path#relpath( + \ vimwiki#path#directory_of_file(s:current_html_file), link_infos.file)) elseif link_infos.scheme =~# '\mwiki\d\+\|diary' " wiki links are always relative to the current file - let html_link = vimwiki#path#relpath( - \ fnamemodify(s:current_wiki_file, ':h'), - \ fnamemodify(link_infos.filename, ':r')) - if html_link !~ '\m/$' - let html_link .= '.html' - endif + let target_html_file = s:corresponding_html_file(link_infos.file) + let html_link = vimwiki#path#to_string(vimwiki#path#relpath( + \ vimwiki#path#directory_of_file(s:current_html_file), target_html_file)) else " other schemes, like http, are left untouched - let html_link = link_infos.filename + let html_link = vimwiki#path#to_string(link_infos.file) endif if link_infos.anchor != '' @@ -1376,57 +1369,61 @@ endfunction function! s:use_custom_wiki2html() let custom_wiki2html = vimwiki#vars#get_wikilocal('custom_wiki2html') - return !empty(custom_wiki2html) && - \ (s:file_exists(custom_wiki2html) || s:binary_exists(custom_wiki2html)) + return vimwiki#path#is_executable(custom_wiki2html) endfunction -function! vimwiki#html#CustomWiki2HTML(path, wikifile, force) - call vimwiki#path#mkdir(a:path) - echomsg system(vimwiki#vars#get_wikilocal('custom_wiki2html'). ' '. - \ a:force. ' '. - \ vimwiki#vars#get_wikilocal('syntax'). ' '. - \ strpart(vimwiki#vars#get_wikilocal('ext'), 1). ' '. - \ shellescape(a:path). ' '. - \ shellescape(a:wikifile). ' '. - \ shellescape(s:default_CSS_full_name(a:path)). ' '. - \ (len(vimwiki#vars#get_wikilocal('template_path')) > 1 ? - \ shellescape(expand(vimwiki#vars#get_wikilocal('template_path'))) : '-'). ' '. - \ (len(vimwiki#vars#get_wikilocal('template_default')) > 0 ? - \ vimwiki#vars#get_wikilocal('template_default') : '-'). ' '. - \ (len(vimwiki#vars#get_wikilocal('template_ext')) > 0 ? - \ vimwiki#vars#get_wikilocal('template_ext') : '-'). ' '. - \ (len(vimwiki#vars#get_bufferlocal('subdir')) > 0 ? - \ shellescape(s:root_path(vimwiki#vars#get_bufferlocal('subdir'))) : '-'). ' '. - \ (len(vimwiki#vars#get_wikilocal('custom_wiki2html_args')) > 0 ? - \ vimwiki#vars#get_wikilocal('custom_wiki2html_args') : '-')) +function! s:call_custom_wiki2HTML(output_dir, wikifile, force) + call vimwiki#path#mkdir(a:output_dir) + + let arguments = [ + \ a:force, + \ vimwiki#vars#get_wikilocal('syntax'), + \ strpart(vimwiki#vars#get_wikilocal('ext'), 1), + \ vimwiki#path#to_string(a:output_dir), + \ vimwiki#path#to_string(a:wikifile), + \ vimwiki#path#to_string(s:default_CSS_full_name()), + \ vimwiki#path#to_string(vimwiki#vars#get_wikilocal('template_path')), + \ vimwiki#vars#get_wikilocal('template_default'), + \ vimwiki#vars#get_wikilocal('template_ext'), + \ vimwiki#path#to_string(s:path_from_subdir_to_root(a:output_dir)), + \ vimwiki#vars#get_wikilocal('custom_wiki2html_args') + \ ] + + for i in range(len(arguments)) + if arguments[i] =~# '\m^\s*$' + let arguments[i] = '-' + endif + let arguments[i] = shellescape(arguments[i]) + endfor + + echomsg system(vimwiki#vars#get_wikilocal('custom_wiki2html'). ' '. join(arguments, ' ')) endfunction -function! s:convert_file(path_html, wikifile) +function! s:convert_file(wikifile) let done = 0 - let wikifile = fnamemodify(a:wikifile, ":p") - - let path_html = expand(a:path_html).vimwiki#vars#get_bufferlocal('subdir') - let htmlfile = fnamemodify(wikifile, ":t:r").'.html' + let html_file = s:corresponding_html_file(a:wikifile) " the currently processed file name is needed when processing links " yeah yeah, shame on me for using (quasi-) global variables - let s:current_wiki_file = wikifile - let s:current_html_file = path_html . htmlfile + let s:current_wiki_file = a:wikifile + let s:current_html_file = html_file + + let output_dir = vimwiki#path#directory_of_file(html_file) if s:use_custom_wiki2html() let force = 1 - call vimwiki#html#CustomWiki2HTML(path_html, wikifile, force) + call s:call_custom_wiki2HTML(output_dir, wikifile, force) let done = 1 endif if s:syntax_supported() && done == 0 - let lsource = readfile(wikifile) + let lsource = readfile(vimwiki#path#to_string(a:wikifile)) let ldest = [] - call vimwiki#path#mkdir(path_html) + call vimwiki#path#mkdir(output_dir) " nohtml placeholder -- to skip html generation. let nohtml = 0 @@ -1492,7 +1489,7 @@ function! s:convert_file(path_html, wikifile) if nohtml echon "\r"."%nohtml placeholder found" - return '' + return vimwiki#path#null_file() endif call s:remove_blank_lines(ldest) @@ -1509,7 +1506,7 @@ function! s:convert_file(path_html, wikifile) call s:close_tag_table(state.table, lines, state.header_ids) call extend(ldest, lines) - let title = s:process_title(placeholders, fnamemodify(a:wikifile, ":t:r")) + let title = s:process_title(placeholders, vimwiki#path#filename(a:wikifile)) let date = s:process_date(placeholders, strftime('%Y-%m-%d')) let html_lines = s:get_html_template(template_name) @@ -1518,10 +1515,9 @@ function! s:convert_file(path_html, wikifile) call map(html_lines, 'substitute(v:val, "%title%", "'. title .'", "g")') call map(html_lines, 'substitute(v:val, "%date%", "'. date .'", "g")') call map(html_lines, 'substitute(v:val, "%root_path%", "'. - \ s:root_path(vimwiki#vars#get_bufferlocal('subdir')) .'", "g")') + \ s:path_from_subdir_to_root(output_dir) .'", "g")') - let css_name = expand(vimwiki#vars#get_wikilocal('css_name')) - let css_name = substitute(css_name, '\', '/', 'g') + let css_name = vimwiki#path#to_string(vimwiki#vars#get_wikilocal('css_name')) call map(html_lines, 'substitute(v:val, "%css%", "'. css_name .'", "g")') let enc = &fileencoding @@ -1532,30 +1528,30 @@ function! s:convert_file(path_html, wikifile) let html_lines = s:html_insert_contents(html_lines, ldest) " %contents% - call writefile(html_lines, path_html.htmlfile) + call writefile(html_lines, vimwiki#path#to_string(html_file)) let done = 1 endif if done == 0 echomsg 'Vimwiki Error: Conversion to HTML is not supported for this syntax' - return '' + return vimwiki#path#null_file() endif - return path_html.htmlfile + return html_file endfunction -function! vimwiki#html#Wiki2HTML(output_dir, wikifile) - let result = s:convert_file(a:output_dir, a:wikifile) - if result != '' - call s:create_default_CSS(a:output_dir) +function! vimwiki#html#Wiki2HTML(wikifile) + let result = s:convert_file(a:wikifile) + if !vimwiki#path#is_null(result) + call s:create_default_CSS() endif return result endfunction -function! vimwiki#html#WikiAll2HTML(path_html) +function! vimwiki#html#WikiAll2HTML() if !s:syntax_supported() && !s:use_custom_wiki2html() echomsg 'Vimwiki Error: Conversion to HTML is not supported for this syntax' return @@ -1569,76 +1565,45 @@ function! vimwiki#html#WikiAll2HTML(path_html) exe 'buffer '.cur_buf let &eventignore = save_eventignore - let path_html = expand(a:path_html) + let path_html = vimwiki#vars#get_wikilocal('path_html') + call vimwiki#path#mkdir(path_html) echomsg 'Vimwiki: Deleting non-wiki html files ...' - call s:delete_html_files(path_html) + call s:delete_html_files() echomsg 'Vimwiki: Converting wiki to html files ...' let setting_more = &more setlocal nomore - " temporarily adjust current_subdir global state variable - let current_subdir = vimwiki#vars#get_bufferlocal('subdir') - let current_invsubdir = vimwiki#vars#get_bufferlocal('invsubdir') - - let wikifiles = split(glob(vimwiki#vars#get_wikilocal('path').'**/*'. - \ vimwiki#vars#get_wikilocal('ext')), '\n') + let wikifiles = vimwiki#path#files_in_dir_recursive(vimwiki#vars#get_wikilocal('path'), + \ vimwiki#vars#get_wikilocal('ext')) for wikifile in wikifiles - let wikifile = fnamemodify(wikifile, ":p") - - " temporarily adjust 'subdir' and 'invsubdir' state variables - let subdir = vimwiki#base#subdir(vimwiki#vars#get_wikilocal('path'), wikifile) - call vimwiki#vars#set_bufferlocal('subdir', subdir) - call vimwiki#vars#set_bufferlocal('invsubdir', vimwiki#base#invsubdir(subdir)) - if !s:is_html_uptodate(wikifile) - echomsg 'Vimwiki: Processing '.wikifile - - call s:convert_file(path_html, wikifile) + echomsg 'Vimwiki: Processing '.vimwiki#path#to_string(wikifile) + call s:convert_file(wikifile) else - echomsg 'Vimwiki: Skipping '.wikifile + echomsg 'Vimwiki: Skipping '.vimwiki#path#to_string(wikifile) endif endfor - " reset 'subdir' state variable - call vimwiki#vars#set_bufferlocal('subdir', current_subdir) - call vimwiki#vars#set_bufferlocal('invsubdir', current_invsubdir) - let created = s:create_default_CSS(path_html) + let created = s:create_default_CSS() if created echomsg 'Vimwiki: Default style.css has been created' endif - echomsg 'Vimwiki: HTML exported to '.path_html + echomsg 'Vimwiki: HTML exported to '.vimwiki#path#to_string(path_html) echomsg 'Vimwiki: Done!' let &more = setting_more endfunction -function! s:file_exists(fname) - return !empty(getftype(expand(a:fname))) -endfunction - - -function! s:binary_exists(fname) - return executable(expand(a:fname)) -endfunction - - -function! s:get_wikifile_url(wikifile) - return vimwiki#vars#get_wikilocal('path_html') . - \ vimwiki#base#subdir(vimwiki#vars#get_wikilocal('path'), a:wikifile). - \ fnamemodify(a:wikifile, ":t:r").'.html' -endfunction - - function! vimwiki#html#PasteUrl(wikifile) - execute 'r !echo file://'.s:get_wikifile_url(a:wikifile) + execute 'r !echo file://'.s:corresponding_html_file(a:wikifile) endfunction function! vimwiki#html#CatUrl(wikifile) - execute '!echo file://'.s:get_wikifile_url(a:wikifile) + execute '!echo file://'.s:corresponding_html_file(a:wikifile) endfunction diff --git a/autoload/vimwiki/path.vim b/autoload/vimwiki/path.vim index 4db1329..3a68892 100644 --- a/autoload/vimwiki/path.vim +++ b/autoload/vimwiki/path.vim @@ -209,9 +209,23 @@ endif " create and return a file object from a string. It is assumed that the given " path is absolute and points to a file (not a directory) function! vimwiki#path#file_obj(filepath) - let filename = fnamemodify(a:filepath, ':p:t') - let path = fnamemodify(a:filepath, ':p:h') - return [vimwiki#path#dir_obj(path), filename] + if a:filepath == '' + return vimwiki#path#null_file() + else + let filename = fnamemodify(a:filepath, ':p:t') + let path = fnamemodify(a:filepath, ':p:h') + return [vimwiki#path#dir_obj(path), filename] + endif +endfunction + + +function! vimwiki#path#null_file() + return [] +endfunction + + +function! vimwiki#path#is_null(file) + return empty(a:file) endfunction @@ -256,6 +270,13 @@ function! vimwiki#path#extension(file_object) endfunction +function! vimwiki#path#set_extension(file_obj, new_ext) + let new_filename = vimwiki#path#filename_without_extension(a:file_obj) . '.' . a:new_ext + let a:file_obj[1] = new_filename + return a:file_obj +endfunction + + function! vimwiki#path#filename_without_extension(file_object) return fnamemodify(a:file_object[1], ':r') endfunction @@ -328,6 +349,7 @@ endfunction " Returns: the relative path from a:dir to a:file +" XXX wenn die beiden identisch sind, sollte . rauskommen function! vimwiki#path#relpath(dir1_object, dir2_object) let dir1_path = copy(a:dir1_object.path) let dir2_path = copy(a:dir2_object.path) @@ -360,15 +382,25 @@ function! vimwiki#path#current_file() return vimwiki#path#file_obj(expand('%:p')) endfunction + function! vimwiki#path#exists(object) if type(a:object) == 4 return isdirectory(vimwiki#path#to_string(a:object)) else + if vimwiki#path#is_null(a:object) + return 0 + endif " glob() checks whether or not a file exists (readable or writable) return glob(vimwiki#path#to_string(a:object)) != '' endif endfunction + +function! vimwiki#path#is_executable(file) + return vimwiki#path#exists(a:file) && executable(vimwiki#path#to_string(a:file)) +endfunction + + " this must be outside a function, because only outside a function expands " to the directory where this file is in let s:vimwiki_autoload_dir = expand(':p:h') diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index bfdc09f..fc3361d 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -242,18 +242,18 @@ endfunction command! -buffer Vimwiki2HTML \ if filewritable(expand('%')) | silent noautocmd w | endif \ - \ let res = vimwiki#html#Wiki2HTML(vimwiki#vars#get_wikilocal('path_html'), vimwiki#path#current_file()) + \ let res = vimwiki#html#Wiki2HTML(vimwiki#path#current_file()) \ - \ if res != '' | echo 'Vimwiki: HTML conversion is done, output: ' + \ if !vimwiki#path#is_null(res) | echo 'Vimwiki: HTML conversion is done, output: ' \ . vimwiki#path#to_string(vimwiki#vars#get_wikilocal('path_html')) | endif command! -buffer Vimwiki2HTMLBrowse \ if filewritable(expand('%')) | silent noautocmd w | endif \ - \ call vimwiki#base#system_open_link(vimwiki#html#Wiki2HTML( - \ vimwiki#vars#get_wikilocal('path_html'), - \ vimwiki#path#current_file())) + \ let result = vimwiki#html#Wiki2HTML(vimwiki#path#current_file()) + \ + \ if !vimwiki#path#is_null(result) | call vimwiki#base#system_open_link(result) | endif command! -buffer VimwikiAll2HTML - \ call vimwiki#html#WikiAll2HTML(vimwiki#vars#get_wikilocal('path_html')) + \ call vimwiki#html#WikiAll2HTML() command! -buffer VimwikiTOC call vimwiki#base#table_of_contents(1) @@ -681,8 +681,7 @@ nnoremap VimwikiGoToPrevSiblingHeader : if vimwiki#vars#get_wikilocal('auto_export') " Automatically generate HTML on page write. augroup vimwiki - au BufWritePost - \ call vimwiki#html#Wiki2HTML(vimwiki#vars#get_wikilocal('path_html'), vimwiki#path#current_file()) + au BufWritePost call vimwiki#html#Wiki2HTML(vimwiki#path#current_file()) augroup END endif