diff --git a/autoload/vimwiki/html.vim b/autoload/vimwiki/html.vim index a6a1f63..a8312a4 100644 --- a/autoload/vimwiki/html.vim +++ b/autoload/vimwiki/html.vim @@ -22,7 +22,7 @@ let g:loaded_vimwiki_html_auto = 1 " UTILITY "{{{ function! s:root_path(subdir) "{{{ - return repeat('../', len(split(a:subdir, '[/\\]'))) + return vimwiki#path#relpath(vimwiki#vars#get_wikilocal('path'), a:subdir) endfunction "}}} function! s:syntax_supported() " {{{ @@ -49,41 +49,20 @@ function! s:is_img_link(lnk) "{{{ return 0 endfunction "}}} -function! s:has_abs_path(fname) "{{{ - if a:fname =~# '\(^.:\)\|\(^/\)' +function! s:default_CSS_full_name(target_dir) " {{{ + return vimwiki#path#join(path, vimwiki#vars#get_wikilocal('css_name')) +endfunction "}}} + +" Returns: 1 if it was createt, 0 if it already existed +function! s:create_default_CSS(target_dir) " {{{ + let css_full_name = s:default_CSS_full_name(a:target_dir) + if vimwiki#path#exists(css_full_name) + return 0 + else + let default_css = vimwiki#path#find_autoload_file('style.css') + call vimwiki#path#copy_file(default_css, css_full_name) return 1 endif - return 0 -endfunction "}}} - -function! s:find_autoload_file(name) " {{{ - for path in split(&runtimepath, ',') - let fname = path.'/autoload/vimwiki/'.a:name - if glob(fname) != '' - return fname - endif - endfor - return '' -endfunction " }}} - -function! s:default_CSS_full_name(path) " {{{ - let path = expand(a:path) - let css_full_name = path . vimwiki#vars#get_wikilocal('css_name') - return css_full_name -endfunction "}}} - -function! s:create_default_CSS(path) " {{{ - let css_full_name = s:default_CSS_full_name(a:path) - if glob(css_full_name) == "" - call vimwiki#path#mkdir(fnamemodify(css_full_name, ':p:h')) - let default_css = s:find_autoload_file('style.css') - if default_css != '' - let lines = readfile(default_css) - call writefile(lines, css_full_name) - return 1 - endif - endif - return 0 endfunction "}}} function! s:template_full_name(name) "{{{ @@ -93,11 +72,12 @@ function! s:template_full_name(name) "{{{ let name = a:name endif - let fname = expand(vimwiki#vars#get_wikilocal('template_path'). - \ name . vimwiki#vars#get_wikilocal('template_ext')) + let filename = vimwiki#path#from_segment_file(name . vimwiki#vars#get_wikilocal('template_ext')) - if filereadable(fname) - return fname + 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 @@ -113,7 +93,7 @@ function! s:get_html_template(template) "{{{ let lines = readfile(template_name) return lines catch /E484/ - echomsg 'Vimwiki: HTML template '.template_name. + echomsg 'Vimwiki: HTML template ' . template_name . \ ' does not exist!' endtry endif @@ -121,7 +101,7 @@ function! s:get_html_template(template) "{{{ let default_tpl = s:template_full_name('') if default_tpl == '' - let default_tpl = s:find_autoload_file('default.tpl') + let default_tpl = vimwiki#path#to_string(vimwiki#path#find_autoload_file('default.tpl')) endif let lines = readfile(default_tpl) @@ -154,7 +134,7 @@ function! s:safe_html_line(line) "{{{ endfunction "}}} function! s:delete_html_files(path) "{{{ - let htmlfiles = split(glob(a:path.'**/*.html'), '\n') + let htmlfiles = vimwiki#path#files_in_dir_recursive(a:path, 'html') for fname in htmlfiles " ignore user html files, e.g. search.html,404.html if stridx(vimwiki#vars#get_global('user_htmls'), fnamemodify(fname, ":t")) >= 0 @@ -1508,10 +1488,10 @@ function! s:convert_file(path_html, wikifile) "{{{ return path_html.htmlfile endfunction "}}} -function! vimwiki#html#Wiki2HTML(path_html, wikifile) "{{{ - let result = s:convert_file(a:path_html, a:wikifile) +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:path_html) + call s:create_default_CSS(a:output_dir) endif return result endfunction "}}} diff --git a/autoload/vimwiki/path.vim b/autoload/vimwiki/path.vim index ffa48c3..a1a90af 100644 --- a/autoload/vimwiki/path.vim +++ b/autoload/vimwiki/path.vim @@ -111,22 +111,21 @@ endfunction "}}} " If the optional argument provided and nonzero, " it will ask before creating a directory " Returns: 1 iff directory exists or successfully created -function! vimwiki#path#mkdir(path, ...) "{{{ - let path = expand(a:path) +function! vimwiki#path#mkdir(dir_obj, ...) "{{{ - if path =~# '^scp:' + if a:dir_obj.protocoll ==# 'scp' " we can not do much, so let's pretend everything is ok return 1 endif - if isdirectory(path) + if vimwiki#path#exists(a:dir_obj) return 1 else if !exists("*mkdir") return 0 endif - let path = vimwiki#path#chomp_slash(path) + let path = vimwiki#path#to_string(a:dir_obj) if vimwiki#u#is_windows() && !empty(vimwiki#vars#get_global('w32_dir_enc')) let path = iconv(path, &enc, vimwiki#vars#get_global('w32_dir_enc')) endif @@ -167,3 +166,157 @@ else return directory . '/' . file endfunction endif + + + +"XXX das kann man aber Einheitstesten! +" XXX überlegen, ob wir auch n Objekt für Wikilinks machen +" Alternativ kann man auch einen Dateipfad als Ordner + Dateinamen modellieren +" The used data types are +" - directory object: a dictionary with the following entries: +" - 'protocoll' -- how to access the file. Supportet are 'scp' or 'file' +" - 'is_unix' -- 1 if it's supposed to be a unix-like path +" - 'path' -- a list containing the directory names starting at the root +" - file object: a list [directory_object, file name] +" - file segment: representing e.g. a relative path. Is a list where the first +" element is a list of directory names and the second the file name + +" create and return a path object from a string. It is assumed that the given +" path is abolute and points to a file (not a directory) +function! vimwiki#path#from_absolute_file(filepath) + let filename = fnamemodify(a:filepath, ':p:t') + let path = fnamemodify(a:filepath, ':p:h') + return [vimwiki#path#from_absolute_dir(path), filename] +endfunction + + +function! vimwiki#path#from_absolute_dir(filepath) + if a:filepath =~# '^scp:' + let filepath = a:filepath[4:] + let protocoll = 'scp' + else + let filepath = resolve(a:filepath) + let protocoll = 'file' + endif + let path = split(vimwiki#path#chomp_slash(filepath), '\m[/\\]', 1) + let is_unix = filepath[0] ==# '/' + let result = { + \ 'is_unix' : is_unix, + \ 'protocoll' : protocoll, + \ 'path' : path, + \} + return result +endfunction + +function! vimwiki#path#current_file() + return vimwiki#path#from_absolute_file(expand('%:p')) +endfunction + +function! vimwiki#path#extension(file_object) + return fnamemodify(a:file_object[1], ':e') +endfunction + +" Returns: the dir of the file object as dir object +function! vimwiki#path#directory(file_object) + return copy(a:file_object[0]) +endfunction + +function! vimwiki#path#filename(file_object) + return a:file_object[1] +endfunction + +" XXX überlegen, ob man das scp vorne dranpackt +function! vimwiki#path#to_string(path) + let dir_obj = type(a:path) == 4 ? a:path : a:path[0] + let separator = dir_obj.is_unix ? '/' : '\' + let address = join(dir_obj.path, separator) . separator + if type(a:path) == 3 + let address .= a:path[1] + endif + return address +endfunction + + +" Assume it is not an absolute path +function! vimwiki#path#from_segment_file(path_segment) + let filename = fnamemodify(a:path_segment, ':t') + let path = fnamemodify(a:filepath, ':h') + let path_list = (path ==# '.' ? [] : split(path, '\m[/\\]', 1)) + return [path_list, filename] +endfunction + + +function! vimwiki#path#join(dir_path, file_segment) + let new_dir_object = copy(a:dir_path) + let new_dir_object.path += a:file_segment[0] + return [new_dir_object, a:file_segment[1]] +endfunction + + +function! vimwiki#path#exists(object) + if type(a:object) == 4 + return isdirectory(vimwiki#path#to_string(a:object)) + else + " glob() checks whether or not a file exists (readable, writable or not) + return glob(vimwiki#path#to_string(a:file_object)) != '' + endif +endfunction + +" returns the segment s, so that jon(dir, s) == file +" we just assume the file is somewhere in dir +function! vimwiki#path#subtract(dir_object, file_object) + let path_rest = a:file_object[0].path[len(a:dir_object.path):] + return [path_rest, file_object[1]] +endfunction + +" Returns: the relative path from a:dir to a:file +function! vimwiki#path#relpath(dir1_object, dir2_object) + let dir1_path = copy(a:dir1_object.path) + let dir2_path = copy(a:dir2_object.path) + let result_path = [] + while (len(dir) > 0 && len(file) > 0) && vimwiki#path#is_equal(dir1_path[0], dir2_path[0]) + call remove(dir1_path, 0) + call remove(dir2_path, 0) + endwhile + for segment in dir1_path + let result += ['..'] + endfor + for segment in dir2_path + let result += [segment] + endfor + let result = { + \ 'is_unix' : a:dir1_object.is_unix, + \ 'protocoll' : a:dir1_object.protocoll, + \ 'path' : result_path, + \} + return result +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') +function! vimwiki#path#find_autoload_file(filename) + let autoload_dir = vimwiki#path#from_absolute_dir(s:vimwiki_autoload_dir) + let filename_obj = vimwiki#path#from_segment_file(a:filename) + let file = vimwiki#path#join(autoload_dir, filename_obj) + if !vimwiki#path#exists(file) + echom 'Vimwiki Error: ' . vimwiki#path#to_string(file) . ' not found' + endif + return file +endfunction + +function! vimwiki#path#copy_file(file_obj, dir_obj) + call vimwiki#path#mkdir(a:dir_obj) + let new_file = deepcopy(a:file_obj) + let new_file[0] = copy(a:dir_obj) + let lines = readfile(vimwiki#path#to_string(a:file_obj)) + let ok = writefile(lines, vimwiki#path#to_string(new_file)) + if ok < 0 + call vimwiki#u#error('Could not write ' . vimwiki#path#to_string(new_file)) + endif +endfunction + +" Returns: a list of all files somewhere in a:dir_obj with extension a:ext +function! vimwiki#path#files_in_dir_recursive(dir_obj, ext) + let htmlfiles = split(glob(a:path.'**/*.html'), '\n') +endfunction diff --git a/autoload/vimwiki/tags.vim b/autoload/vimwiki/tags.vim index 490b47d..9582df5 100644 --- a/autoload/vimwiki/tags.vim +++ b/autoload/vimwiki/tags.vim @@ -28,7 +28,7 @@ function! vimwiki#tags#update_tags(full_rebuild, all_files) "{{{ let all_files = a:all_files != '' if !a:full_rebuild " Updating for one page (current) - let page_name = vimwiki#vars#get_bufferlocal('subdir') . expand('%:t:r') + let page_name = s:page_name(vimwiki#path#current_file()) " Collect tags in current file let tags = s:scan_tags(getline(1, '$'), page_name) " Load metadata file @@ -41,14 +41,12 @@ function! vimwiki#tags#update_tags(full_rebuild, all_files) "{{{ call s:write_tags_metadata(metadata) else " full rebuild let files = vimwiki#base#find_files(vimwiki#vars#get_bufferlocal('wiki_nr'), 0) - let wiki_base_dir = vimwiki#vars#get_wikilocal('path') let tags_file_last_modification = - \ getftime(vimwiki#tags#metadata_file_path()) + \ getftime(vimwiki#path#to_string(vimwiki#tags#metadata_file_path())) let metadata = s:load_tags_metadata() for file in files - if all_files || getftime(file) >= tags_file_last_modification - let subdir = vimwiki#base#subdir(wiki_base_dir, file) - let page_name = subdir . fnamemodify(file, ':t:r') + if all_files || getftime(vimwiki#path#to_string(file)) >= tags_file_last_modification + let page_name = s:page_name(file) let tags = s:scan_tags(readfile(file), page_name) let metadata = s:remove_page_from_tags(metadata, page_name) let metadata = s:merge_tags(metadata, page_name, tags) @@ -58,6 +56,12 @@ function! vimwiki#tags#update_tags(full_rebuild, all_files) "{{{ endif endfunction " }}} +function! s:page_name(file_obj) + let wiki_base_dir = vimwiki#vars#get_wikilocal('path') + let segment = vimwiki#path#subtract(wiki_base_dir, a:file_obj) + return vimwiki#path#to_string(segment) +endfunction + " s:scan_tags " Scans the list of text lines (argument) and produces tags metadata as a " list of tag entries. @@ -139,9 +143,9 @@ function! s:scan_tags(lines, page_name) "{{{ endfunction " }}} " vimwiki#tags#metadata_file_path -" Returns tags metadata file path +" Returns tags metadata file path object function! vimwiki#tags#metadata_file_path() abort "{{{ - return fnamemodify(vimwiki#path#join_path(vimwiki#vars#get_wikilocal('path'), s:TAGS_METADATA_FILE_NAME), ':p') + return vimwiki#path#join(vimwiki#vars#get_wikilocal('path'), vimwiki#path#from_segment_file(s:TAGS_METADATA_FILE_NAME)) endfunction " }}} " s:load_tags_metadata diff --git a/autoload/vimwiki/u.vim b/autoload/vimwiki/u.vim index 009bf9d..bf779ce 100644 --- a/autoload/vimwiki/u.vim +++ b/autoload/vimwiki/u.vim @@ -61,3 +61,8 @@ else return &sw endfunc endif "}}} + + +function vimwiki#u#error(message) + echom 'Vimwiki Error: ' . a:message +endfunction diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index e5763f3..31cb784 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -29,7 +29,7 @@ execute 'setlocal suffixesadd='.vimwiki#vars#get_wikilocal('ext') setlocal isfname-=[,] " gf}}} -exe "setlocal tags+=" . escape(vimwiki#tags#metadata_file_path(), ' \|"') +exe "setlocal tags+=" . escape(vimwiki#path#to_string(vimwiki#tags#metadata_file_path()), ' \|"') " MISC }}} @@ -106,7 +106,7 @@ function! Complete_wikifiles(findstart, base) let segments = split(a:base, '#', 1) let given_wikifile = segments[0] == '' ? expand('%:t:r') : segments[0] let link_infos = vimwiki#base#resolve_link(given_wikifile.'#') - let wikifile = link_infos.filename + let wikifile = link_infos.path let syntax = vimwiki#vars#get_wikilocal('syntax', link_infos.index) let anchors = vimwiki#base#get_anchors(wikifile, syntax) @@ -243,18 +243,17 @@ endfunction "}}} command! -buffer Vimwiki2HTML \ if filewritable(expand('%')) | silent noautocmd w | endif \ - \ let res = vimwiki#html#Wiki2HTML(expand(vimwiki#vars#get_wikilocal('path_html')), - \ expand('%')) + \ let res = vimwiki#html#Wiki2HTML(vimwiki#vars#get_wikilocal('path_html'), vimwiki#path#current_file()) \ - \ if res != '' | echo 'Vimwiki: HTML conversion is done, output: ' . expand(vimwiki#vars#get_wikilocal('path_html')) | endif + \ if 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( - \ expand(vimwiki#vars#get_wikilocal('path_html')), - \ expand('%'))) + \ vimwiki#vars#get_wikilocal('path_html'), + \ vimwiki#path#current_file())) command! -buffer VimwikiAll2HTML - \ call vimwiki#html#WikiAll2HTML(expand(vimwiki#vars#get_wikilocal('path_html'))) + \ call vimwiki#html#WikiAll2HTML(vimwiki#vars#get_wikilocal('path_html')) command! -buffer VimwikiTOC call vimwiki#base#table_of_contents(1) @@ -277,10 +276,10 @@ command! -buffer -nargs=0 VimwikiBacklinks call vimwiki#base#backlinks() command! -buffer -nargs=0 VWB call vimwiki#base#backlinks() exe 'command! -buffer -nargs=* VimwikiSearch lvimgrep '. - \ escape(vimwiki#vars#get_wikilocal('path').'**/*'.vimwiki#vars#get_wikilocal('ext'), ' ') + \ escape(vimwiki#path#to_string(vimwiki#vars#get_wikilocal('path')).'**/*'.vimwiki#vars#get_wikilocal('ext'), ' ') exe 'command! -buffer -nargs=* VWS lvimgrep '. - \ escape(vimwiki#vars#get_wikilocal('path').'**/*'.vimwiki#vars#get_wikilocal('ext'), ' ') + \ escape(vimwiki#path#to_string(vimwiki#vars#get_wikilocal('path')).'**/*'.vimwiki#vars#get_wikilocal('ext'), ' ') command! -buffer -nargs=+ -complete=custom,vimwiki#base#complete_links_escaped \ VimwikiGoto call vimwiki#base#goto() @@ -641,8 +640,7 @@ if vimwiki#vars#get_wikilocal('auto_export') " Automatically generate HTML on page write. augroup vimwiki au BufWritePost - \ call vimwiki#html#Wiki2HTML(expand(vimwiki#vars#get_wikilocal('path_html')), - \ expand('%')) + \ call vimwiki#html#Wiki2HTML(vimwiki#vars#get_wikilocal('path_html'), vimwiki#path#current_file()) augroup END endif diff --git a/plugin/vimwiki.vim b/plugin/vimwiki.vim index 13797f8..0eb33ae 100644 --- a/plugin/vimwiki.vim +++ b/plugin/vimwiki.vim @@ -30,8 +30,9 @@ endfunction "}}} " create a new temporary wiki for the current buffer function! s:create_temporary_wiki() - let path = expand('%:p:h') - let ext = '.'.expand('%:e') + let current_file = vimwiki#path#current_file() + let path = vimwiki#path#directory(current_file) + let ext = '.'.vimwiki#path#extension(current_file) let syntax_mapping = vimwiki#vars#get_global('ext2syntax') if has_key(syntax_mapping, ext) @@ -124,7 +125,7 @@ function! s:setup_buffer_enter() "{{{ " lcd as well if vimwiki#vars#get_global('auto_chdir') - exe 'lcd' vimwiki#vars#get_wikilocal('path') + exe 'lcd' vimwiki#path#to_string(vimwiki#vars#get_wikilocal('path')) endif " Set up menu @@ -292,8 +293,8 @@ nnoremap