From c9ba53e204a64d106fe4e2c3208f60ebe17eb202 Mon Sep 17 00:00:00 2001 From: Tinmarino Date: Sat, 25 Jul 2020 03:40:50 -0400 Subject: [PATCH] Refractor: Path Add utility unixify #478 Basically unixify all before workingm then transofom in function os os Util: Add function sort_len that a list of string according to the lenght of its content Fix: VimwikiRenameLink doesn't update links in diary #90 Test: VimwikiRenameLink with nested directories Prettify comments in autoload/path + remove antipattern Define osxify function helper to solve windows Vs Unix : see #478 Path: remove useless temporary fix convertion before calling relpath (redundant) : see #478 Test: Fix typo Path corrected (Thanks to test) --- autoload/vimwiki/base.vim | 8 --- autoload/vimwiki/path.vim | 116 ++++++++++++++++++--------------- autoload/vimwiki/u.vim | 10 +++ doc/vimwiki.txt | 3 +- test/command_rename_link.vader | 3 +- 5 files changed, 78 insertions(+), 62 deletions(-) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index 93f142f..da45e9c 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -572,10 +572,6 @@ function! vimwiki#base#get_wikilinks(wiki_nr, also_absolute_links, pattern) abor let result = [] for wikifile in files let wikifile = fnamemodify(wikifile, ':r') " strip extension - if vimwiki#u#is_windows() - " TODO temporary fix see #478 - let wikifile = substitute(wikifile , '/', '\', 'g') - endif let wikifile = vimwiki#path#relpath(cwd, wikifile) call add(result, wikifile) endfor @@ -587,10 +583,6 @@ function! vimwiki#base#get_wikilinks(wiki_nr, also_absolute_links, pattern) abor let cwd = vimwiki#vars#get_wikilocal('path') . vimwiki#vars#get_wikilocal('diary_rel_path') endif let wikifile = fnamemodify(wikifile, ':r') " strip extension - if vimwiki#u#is_windows() - " TODO temporary fix see #478 - let wikifile = substitute(wikifile , '/', '\', 'g') - endif let wikifile = '/'.vimwiki#path#relpath(cwd, wikifile) call add(result, wikifile) endfor diff --git a/autoload/vimwiki/path.vim b/autoload/vimwiki/path.vim index 7b8bbb1..05f98ba 100644 --- a/autoload/vimwiki/path.vim +++ b/autoload/vimwiki/path.vim @@ -4,7 +4,32 @@ " Home: https://github.com/vimwiki/vimwiki/ -" Remove: trailing / + +" Unixify path +function! s:unixify(path) abort + return substitute(a:path, '\', '/', 'g') +endfunction + + +" Windowsify path +function! s:windowsify(path) abort + return substitute(a:path, '/', '\', 'g') +endfunction + + +" Define os specific path convertion +if vimwiki#u#is_windows() + function! s:osxify(path) abort + return s:windowsify(a:path) + endfunction +else + function! s:osxify(path) abort + return s:unixify(a:path) + endfunction +endif + + +" Remove last path delimitator (slash or backslash) function! vimwiki#path#chomp_slash(str) abort return substitute(a:str, '[/\\]\+$', '', '') endfunction @@ -22,7 +47,7 @@ else endif -" Collapse: sections like /a/b/../c to /a/c and /a/b/./c to /a/b/c +" Collapse sections like /a/b/../c to /a/c and /a/b/./c to /a/b/c function! vimwiki#path#normalize(path) abort let path = a:path while 1 @@ -37,36 +62,34 @@ function! vimwiki#path#normalize(path) abort endfunction -" Normalize: Convert \ -> / +" Normalize path: \ -> / && /// -> / && resolve(symlinks) function! vimwiki#path#path_norm(path) abort - " /-slashes - if a:path !~# '^scp:' - let path = substitute(a:path, '\', '/', 'g') - " treat multiple consecutive slashes as one path separator - let path = substitute(path, '/\+', '/', 'g') - " ensure that we are not fooled by a symbolic link - return resolve(path) - else - return a:path - endif + " return if scp + if a:path =~# '^scp:' | return a:path | endif + " convert backslash to slash + let path = substitute(a:path, '\', '/', 'g') + " treat multiple consecutive slashes as one path separator + let path = substitute(path, '/\+', '/', 'g') + " ensure that we are not fooled by a symbolic link + return resolve(path) endfunction -" Check: if link is to a directory. +" Check if link is to a directory function! vimwiki#path#is_link_to_dir(link) abort " It should be ended with \ or /. return a:link =~# '\m[/\\]$' endfunction -" Return: Absolute path, from a relative link +" Get absolute path <- path relative to current file function! vimwiki#path#abs_path_of_link(link) abort return vimwiki#path#normalize(expand('%:p:h').'/'.a:link) endfunction -" Return: longest common path prefix of 2 given paths. -" '~/home/usrname/wiki', '~/home/usrname/wiki/shmiki' => '~/home/usrname/wiki' +" Returns: longest common path prefix of 2 given paths. +" Ex: '~/home/usrname/wiki', '~/home/usrname/wiki/shmiki' => '~/home/usrname/wiki' function! vimwiki#path#path_common_pfx(path1, path2) abort let p1 = split(a:path1, '[/\\]', 1) let p2 = split(a:path2, '[/\\]', 1) @@ -84,7 +107,7 @@ function! vimwiki#path#path_common_pfx(path1, path2) abort endfunction -" Return: Relative path +" Convert path -> full resolved slashed path function! vimwiki#path#wikify_path(path) abort let result = resolve(fnamemodify(a:path, ':p')) if vimwiki#u#is_windows() @@ -107,50 +130,41 @@ function! vimwiki#path#relpath(dir, file) abort if empty(a:dir) || a:dir =~# '^\.[/\\]\?$' return a:file endif - let result = [] - if vimwiki#u#is_windows() - " TODO temporary fix see #478 - " not sure why paths get converted back to using forward slash - " when passed to the function in the form C:\path\to\file - let dir = substitute(a:dir, '/', '\', 'g') - let file = substitute(a:file, '/', '\', 'g') - let dir = split(dir, '\') - let file = split(file, '\') - else - let dir = split(a:dir, '/') - let file = split(a:file, '/') - endif + " Unixify && Expand in + let s_dir = expand(s:unixify(a:dir)) + let s_file = expand(s:unixify(a:file)) + + " Split path + let dir = split(s_dir, '/') + let file = split(s_file, '/') + + " Shorten loop till equality while (len(dir) > 0 && len(file) > 0) && vimwiki#path#is_equal(dir[0], file[0]) call remove(dir, 0) call remove(file, 0) endwhile + + " Return './' if nothing left if empty(dir) && empty(file) - if vimwiki#u#is_windows() - " TODO temporary fix see #478 - return '.\' - else - return './' - endif + return s:osxify('./') endif + + " Build path segment + let segments = [] for segment in dir - let result += ['..'] + let segments += ['..'] endfor for segment in file - let result += [segment] + let segments += [segment] endfor - if vimwiki#u#is_windows() - " TODO temporary fix see #478 - let result_path = join(result, '\') - if a:file =~? '\m\\$' - let result_path .= '\' - endif - else - let result_path = join(result, '/') - if a:file =~? '\m/$' - let result_path .= '/' - endif + + " Join segments + let result_path = join(segments, '/') + if a:file =~# '\m/$' + let result_path .= '/' endif - return result_path + + return s:osxify(result_path) endfunction diff --git a/autoload/vimwiki/u.vim b/autoload/vimwiki/u.vim index 4cfbc3f..588d96b 100644 --- a/autoload/vimwiki/u.vim +++ b/autoload/vimwiki/u.vim @@ -62,6 +62,16 @@ endfunction " Trim spaces: leading and trailing +function! vimwiki#u#sort_len(list) abort + function! s:len_compare(s1, s2) abort + let i1 = len(a:s1) + let i2 = len(a:s2) + return i1 == i2 ? 0 : i1 > i2 ? 1 : -1 + endfunction + return sort(a:list, 's:len_compare') +endfunction + + function! vimwiki#u#trim(string, ...) abort let chars = '' if a:0 > 0 diff --git a/doc/vimwiki.txt b/doc/vimwiki.txt index 5d61dc1..6db5b9e 100644 --- a/doc/vimwiki.txt +++ b/doc/vimwiki.txt @@ -808,7 +808,7 @@ Vimwiki file. The status of parents is updated accordingly. If you want to remove only items of the current nesting level, (re)define a command that calls the same function with `0` as first argument: > - :command! -buffer -range VimwikiRemoveDone call + :command! -buffer -range VimwikiRemoveDone call \ vimwiki#lst#remove_done(0, "", , ) < *:VimwikiNextTask* @@ -3675,6 +3675,7 @@ Contributors and their Github usernames in roughly chronological order: - Rafael Castillo (@eltrufas) - Reiner Herrmann (@reinerh) + ============================================================================== 16. Changelog *vimwiki-changelog* diff --git a/test/command_rename_link.vader b/test/command_rename_link.vader index 72c655b..1bf1205 100644 --- a/test/command_rename_link.vader +++ b/test/command_rename_link.vader @@ -129,7 +129,6 @@ Expect (Link to in_dir11_new): [dir2 in_dir2](dir2/in_dir2.md) - Do (in_dir2 -> in_dir2_new): :edit $HOME/testmarkdown/dir2/in_dir2.md\ @@ -148,7 +147,7 @@ Do (in_dir2 -> in_dir2_new): Expect (old and new filenames): - + /home/vimtest/testmarkdown/dir2/in_dir2.md /home/vimtest/testmarkdown/dir2/in_dir2_new.md