-
Notifications
You must be signed in to change notification settings - Fork 66
Feature: More flexible handling of URLs #302
Description
This feature request is a result of the discussion in #296 and work on this should probably wait for #301 to be addressed.
wiki.vim has a relatively robust implementation of links as a concept. The idea is to parse various types of links and to enrich the parsed result with some methods that are used by the "public" APIs and mappings/commands. The parsed result will find a URL, then we figure out the proper URL scheme, then the link.follow function will use the handler from the corresponding autoload/wiki/url/SCHEME.vim file.
This works well in the sense that it is easy to add new scheme handlers as a developer. But the user flexibility is not very large. There are some options, like g:wiki_resolver and g:wiki_file_handler that are used by the wiki scheme and the file scheme, respectively.
It seems it could be a better idea to generalize the concept and provide an option that allows full flexibility for users to define their own handlers. For that purpose, it is useful to divide the relevant actions in two:
- A resolver function that takes the original URL and parses it.
- A handler function that takes the output of the resolver and acts on it; e.g. open the target in a new window in Vim or in an external viewer.
By splitting these, we make it easier to apply customizations on only parts of the "flow"; e.g. a user could adjust how a link is opened, another user could change how the URL should be parsed.
The configuration option could look something like this:
*g:wiki_link_schemes*
A dictionary to configure resolvers and handlers URL schemes. The keys
represent the schemes and the values are dictionaries that configure
the behaviour for the specified scheme through two concepts:
resolver ~
A function that parses the original URL (a string argument). If no such
function is defined, then the handler will receive the original URL
directly.
handler ~
A function that takes the result(s) of the `resolver` function and acts
on it.
Notice that the `resolver` and `handler` needs to "fit". If the `resolver`
returns a string, then the `handler` must take a string as an argument.
Both `resolver` and `handler` must be of type |Funcref|.
Default: >vim
let g:wiki_link_schemes = {
\ 'wiki': {
\ 'resolver': function('wiki#link#resolver#wiki'),
\ 'handler': function('wiki#link#handler#wiki'),
\ },
\ 'file': {
\ 'resolver': '',
\ 'handler': function('wiki#link#handler#file'),
\ },
\ …
\}I believe this would bring a lot of value to users in form of customization. It would also mean that it would be trivial to implement support for new schemes, as it would be enough to add them to this new option.
Implementing this is a relatively large job. All the current handlers and resolvers would need to be changed; I would propose moving them to autoload/wiki/link/{resolver,handler}.vim and to make all of them "pure" functions. And, of course, we would need to adjust how the link objects are created and move the .follow() methods back to the link object; something like this:
function s:link.follow() abort dict
let l:resolved_url = self.resolver(self.url)
call self.handler(l:resolved_url)
endfunction