diff --git a/autoload/fugitive.vim b/autoload/fugitive.vim index beb15ee..6a59b95 100644 --- a/autoload/fugitive.vim +++ b/autoload/fugitive.vim @@ -80,6 +80,14 @@ function! s:fnameescape(file) abort endif endfunction +function! fugitive#UrlDecode(str) abort + return substitute(a:str, '%\(\x\x\)', '\=iconv(nr2char("0x".submatch(1)), "utf-8", "latin1")', 'g') +endfunction + +function! s:UrlEncode(str) abort + return substitute(a:str, '[%#?&;+\<> [:cntrl:]]', '\=printf("%%%02X", char2nr(submatch(0)))', 'g') +endfunction + function! s:throw(string) abort throw 'fugitive: '.a:string endfunction @@ -1315,15 +1323,15 @@ endfunction function! s:UrlParse(url) abort let scp_authority = matchstr(a:url, '^[^:/]\+\ze:\%(//\)\@!') if len(scp_authority) && !(has('win32') && scp_authority =~# '^\a:[\/]') - let url = {'scheme': 'ssh', 'authority': scp_authority, 'hash': '', - \ 'path': substitute(strpart(a:url, len(scp_authority) + 1), '[#?]', '\=printf("%%%02X", char2nr(submatch(0)))', 'g')} + let url = {'scheme': 'ssh', 'authority': s:UrlEncode(scp_authority), 'hash': '', + \ 'path': s:UrlEncode(strpart(a:url, len(scp_authority) + 1))} elseif empty(a:url) let url = {'scheme': '', 'authority': '', 'path': '', 'hash': ''} else let match = matchlist(a:url, '^\([[:alnum:].+-]\+\)://\([^/]*\)\(/[^#]*\)\=\(#.*\)\=$') if empty(match) let url = {'scheme': 'file', 'authority': '', 'hash': '', - \ 'path': substitute(a:url, '[#?]', '\=printf("%%%02X", char2nr(submatch(0)))', 'g')} + \ 'path': s:UrlEncode(a:url)} else let url = {'scheme': match[1], 'authority': match[2], 'hash': match[4]} let url.path = empty(match[3]) ? '/' : match[3] @@ -1335,7 +1343,7 @@ endfunction function! s:UrlPopulate(string, into) abort let url = a:into let url.protocol = substitute(url.scheme, '.\zs$', ':', '') - let url.user = matchstr(url.authority, '.\{-\}\ze@', '', '') + let url.user = fugitive#UrlDecode(matchstr(url.authority, '.\{-\}\ze@', '', '')) let url.host = substitute(url.authority, '.\{-\}@', '', '') let url.hostname = substitute(url.host, ':\d\+$', '', '') let url.port = matchstr(url.host, ':\zs\d\+$', '', '') @@ -1354,6 +1362,7 @@ function! s:UrlPopulate(string, into) abort else let url.href = a:string endif + let url.path = fugitive#UrlDecode(matchstr(url.path, '^[^?]*')) let url.url = matchstr(url.href, '^[^#]*') endfunction