diff --git a/autoload/fern/fri.vim b/autoload/fern/fri.vim index cb3b8b7f..65885866 100644 --- a/autoload/fern/fri.vim +++ b/autoload/fern/fri.vim @@ -22,7 +22,7 @@ function! fern#fri#parse(expr) abort endif let [authority, remains] = s:split1(remains, escape('/', s:PATTERN)) if empty(remains) - let remaings = authority + let remains = authority let authority = '' endif let [path, remains] = s:split1(remains, escape(';', s:PATTERN)) @@ -74,7 +74,7 @@ function! s:parse_query(query) abort call map(terms, { _, v -> (split(v, '=', 1) + [v:true])[:1] }) call map(terms, { _, v -> \ extend(obj, { - \ s:decode(v[0]): s:decode(v[1]) + \ s:decode(v[0]): type(v[1]) is# v:t_string ? s:decode(v[1]) : v[1], \ }) \}) return obj @@ -123,22 +123,13 @@ function! s:encode_fragment(pchar) abort endfunction function! s:encode(str, pattern) abort - let chars = map( - \ split(a:str, '\zs'), - \ { _, v -> v =~# a:pattern ? printf('%%%X', char2nr(v)) : v }, - \) - return join(chars, '') + let Sub = { m -> printf('%%%X', char2nr(m[0])) } + return substitute(a:str, a:pattern, Sub, 'g') endfunction function! s:decode(str) abort - let str = a:str - let [hex, s, e] = matchstrpos(str, '%\zs[0-9a-fA-F]\{2}') - while !empty(hex) - let repl = nr2char(str2nr(hex, 16)) - let str = substitute(str, '%' . hex, escape(repl, '&'), 'ig') - let [hex, s, e] = matchstrpos(str, '%\zs[0-9a-fA-F]\{2}', s + 1) - endwhile - return str + let Sub = { m -> nr2char(str2nr(m[1], 16)) } + return substitute(a:str, '%\([0-9a-fA-F]\{2}\)', Sub, 'g') endfunction function! s:split1(str, pattern) abort diff --git a/test/fern/fri.vimspec b/test/fern/fri.vimspec index fd3b50c2..621ad1e3 100644 --- a/test/fern/fri.vimspec +++ b/test/fern/fri.vimspec @@ -127,6 +127,30 @@ Describe fern#fri \} Assert Equals(fern#fri#parse(expr), want) End + + It returns FRI for 'file:///foo%20bar%20baz' + let expr = 'file:///foo%20bar%20baz' + let want = { + \ 'scheme': 'file', + \ 'authority': '', + \ 'path': 'foo bar baz', + \ 'query': {}, + \ 'fragment': '', + \} + Assert Equals(fern#fri#parse(expr), want) + End + + It returns FRI for 'fri://qux/file:///foo%252520bar%252520baz' + let expr = 'fri://qux/file:///foo%252520bar%252520baz' + let want = { + \ 'scheme': 'fri', + \ 'authority': 'qux', + \ 'path': 'file:///foo%2520bar%2520baz', + \ 'query': {}, + \ 'fragment': '', + \} + Assert Equals(fern#fri#parse(expr), want) + End End Describe #format() @@ -200,6 +224,30 @@ Describe fern#fri \} Assert Equals(fern#fri#format(want), expr) End + + It formats FRI to 'file:///foo%20bar%20baz' + let expr = 'file:///foo%20bar%20baz' + let want = { + \ 'scheme': 'file', + \ 'authority': '', + \ 'path': 'foo bar baz', + \ 'query': {}, + \ 'fragment': '', + \} + Assert Equals(fern#fri#format(want), expr) + End + + It formats FRI to 'fri://qux/file:///foo%252520bar%252520baz' + let expr = 'fri://qux/file:///foo%252520bar%252520baz' + let want = { + \ 'scheme': 'fri', + \ 'authority': 'qux', + \ 'path': 'file:///foo%2520bar%2520baz', + \ 'query': {}, + \ 'fragment': '', + \} + Assert Equals(fern#fri#format(want), expr) + End End Describe #encode() @@ -228,6 +276,15 @@ Describe fern#fri Assert Equals(fern#fri#encode('=', pattern), '%3D') Assert Equals(fern#fri#encode(' ', pattern), '%20') End + + It encodes all percent character (%) + Assert Equals(fern#fri#encode('%%'), '%25%25') + End + + It encodes not a string then returns a string + Assert Same(fern#fri#encode(v:true), 'v:true') + Assert Same(fern#fri#encode(42), '42') + End End Describe #decode() @@ -256,5 +313,20 @@ Describe fern#fri Assert Equals(fern#fri#decode('%2523'), '%23') Assert Equals(fern#fri#decode('%23'), '#') End + + It decodes all percent character (%) + Assert Equals(fern#fri#decode('%23%23'), '##') + End + + It decodes all percent character (%) only one depth + Assert Equals(fern#fri#decode('%252523%252523'), '%2523%2523') + Assert Equals(fern#fri#decode('%2523%2523'), '%23%23') + Assert Equals(fern#fri#decode('%23%23'), '##') + End + + It decodes not a string then returns a string + Assert Same(fern#fri#decode(v:true), 'v:true') + Assert Same(fern#fri#decode(42), '42') + End End End