diff --git a/autoload/wiki/link.vim b/autoload/wiki/link.vim index 33669081..f02db8f9 100644 --- a/autoload/wiki/link.vim +++ b/autoload/wiki/link.vim @@ -74,6 +74,17 @@ function! wiki#link#get_creator(...) abort " {{{1 return a:0 > 0 ? l:c[a:1] : l:c endfunction +" }}}1 +function! wiki#link#get_scheme(link_type) abort " {{{1 + let l:scheme = get(g:wiki_link_default_schemes, a:link_type, '') + + if type(l:scheme) == v:t_dict + let l:scheme = get(l:scheme, expand('%:e'), '') + endif + + return l:scheme +endfunction + " }}}1 function! wiki#link#show(...) abort "{{{1 @@ -82,7 +93,17 @@ function! wiki#link#show(...) abort "{{{1 if empty(l:link) || l:link.type ==# 'word' call wiki#log#info('No link detected') else - call wiki#log#info('Link info', l:link.pprint()) + let l:viewer = { + \ 'name': 'WikiLinkInfo', + \ 'items': l:link.describe() + \} + function! l:viewer.print_content() abort dict + for [l:key, l:value] in self.items + call append('$', printf(' %-14s %s', l:key, l:value)) + endfor + endfunction + + call wiki#scratch#new(l:viewer) endif endfunction @@ -216,7 +237,7 @@ let s:matchers = [ \ wiki#link#ref_collapsed#matcher(), \ wiki#link#ref_full#matcher(), \ wiki#link#url#matcher(), - \ wiki#link#shortcite#matcher(), + \ wiki#link#cite#matcher(), \ wiki#link#date#matcher(), \ wiki#link#word#matcher(), \] @@ -231,7 +252,7 @@ let s:matchers_real = [ \ wiki#link#org#matcher(), \ wiki#link#ref_definition#matcher(), \ wiki#link#url#matcher(), - \ wiki#link#shortcite#matcher(), + \ wiki#link#cite#matcher(), \] " }}}1 diff --git a/autoload/wiki/link/_template.vim b/autoload/wiki/link/_template.vim index 2e6ebde7..596dfc15 100644 --- a/autoload/wiki/link/_template.vim +++ b/autoload/wiki/link/_template.vim @@ -45,8 +45,8 @@ function! s:matcher.create_link(match) dict abort " {{{1 " Get link text let l:match.text = '' - if has_key(self, 'rx_text') - let [l:text, l:c1, l:c2] = s:matchstrpos(l:match.content, self.rx_text) + if has_key(l:match, 'rx_text') + let [l:text, l:c1, l:c2] = s:matchstrpos(l:match.content, l:match.rx_text) if !empty(l:text) let l:match.text = l:text let l:match.text_pos_start = [l:match.pos_start[0], l:match.pos_start[1] + l:c1] @@ -56,8 +56,8 @@ function! s:matcher.create_link(match) dict abort " {{{1 " Get link url let l:match.url = l:match.content - if has_key(self, 'rx_url') - let [l:url, l:c1, l:c2] = s:matchstrpos(l:match.content, self.rx_url) + if has_key(l:match, 'rx_url') + let [l:url, l:c1, l:c2] = s:matchstrpos(l:match.content, l:match.rx_url) if !empty(l:url) let l:match.url = l:url let l:match.url_pos_start = [l:match.pos_start[0], l:match.pos_start[1] + l:c1] @@ -66,13 +66,19 @@ function! s:matcher.create_link(match) dict abort " {{{1 endif let l:match.url_raw = l:match.url - " Matcher specific url parsing - call l:match.parse_url() + " Add scheme to URL if it is missing + let l:match.default_scheme = wiki#link#get_scheme(l:match.type) + if empty(matchstr(l:match.url, '^\w\+:')) + if !empty(l:match.default_scheme) + let l:match.url = l:match.default_scheme . ':' . l:match.url + endif + endif + let l:match.scheme = matchstr(l:match.url, '^\w\+:') " Add toggle function if !has_key(l:match, 'toggle_template') - \ && has_key(g:wiki_link_toggles, self.type) - let l:match.toggle_template = function(g:wiki_link_toggles[self.type]) + \ && has_key(g:wiki_link_toggles, l:match.type) + let l:match.toggle_template = function(g:wiki_link_toggles[l:match.type]) endif " Clean up @@ -81,20 +87,17 @@ function! s:matcher.create_link(match) dict abort " {{{1 silent! unlet l:match.rx_text silent! unlet l:match.create_link silent! unlet l:match.match_at_cursor - silent! unlet l:match.parse_url + + if has_key(l:match, 'create_link_post') + call l:match.create_link_post() + unlet l:match.create_link_post + endif " Return the parsed link return s:link.new(l:match) endfunction "}}}1 -function! s:matcher.parse_url() dict abort " {{{1 - if !empty(get(self, 'scheme', '')) && empty(matchstr(self.url, '^\w\+:')) - let self.url = self.scheme . ':' . self.url - endif -endfunction - -" }}}1 let s:link = {} @@ -120,33 +123,20 @@ function! s:link.replace(text) dict abort " {{{1 endfunction " }}}1 -function! s:link.pprint() dict abort " {{{1 - let l:out = { - \ 'type': self.type, - \ 'scheme': get(self, 'scheme', 'NONE'), - \ 'text': get(self, 'text', ''), - \ 'url': self.url, - \ 'raw_url': self.url_raw, - \ 'raw': self.content, - \ 'follow': string(get(self, 'follow', '')), - \ 'toggle_template': string(get(self, 'toggle_template', '')), - \} - if l:out.raw_url ==# l:out.url - unlet l:out.raw_url - endif - if l:out.raw ==# l:out.url - unlet l:out.raw - endif - if empty(l:out.text) - unlet l:out.text - endif - if empty(l:out.follow) - unlet l:out.follow +function! s:link.describe() dict abort " {{{1 + let l:content = [ + \ ['Type:', self.type], + \ ['Match:', self.content], + \ ['URL:', self.url], + \] + + if self.url !=# self.url_raw + let l:content += [['URL (raw):', self.url_raw]] endif - if empty(l:out.toggle_template) - unlet l:out.toggle_template - endif - return l:out + + let l:content += [['Description:', empty(self.text) ? 'N/A' : self.text]] + + return l:content endfunction " }}}1 diff --git a/autoload/wiki/link/adoc_link.vim b/autoload/wiki/link/adoc_link.vim index 1364e5ab..79589699 100644 --- a/autoload/wiki/link/adoc_link.vim +++ b/autoload/wiki/link/adoc_link.vim @@ -6,7 +6,6 @@ function! wiki#link#adoc_link#matcher() abort " {{{1 return extend(wiki#link#_template#matcher(), { - \ 'scheme': 'file', \ 'type': 'adoc_link', \ 'rx': g:wiki#rx#link_adoc_link, \ 'rx_url': '\<<\zs\%([^,>]\{-}\ze,[^>]\{-}\|[^>]\{-}\ze\)>>', \ 'rx_text': '<<[^,>]\{-},\zs[^>]\{-}\ze>>', diff --git a/autoload/wiki/link/adoc_xref_inline.vim b/autoload/wiki/link/adoc_xref_inline.vim index 9c811a36..9da46b84 100644 --- a/autoload/wiki/link/adoc_xref_inline.vim +++ b/autoload/wiki/link/adoc_xref_inline.vim @@ -7,7 +7,6 @@ function! wiki#link#adoc_xref_inline#matcher() abort " {{{1 return extend(wiki#link#_template#matcher(), { \ 'type': 'adoc_xref_inline', - \ 'scheme': 'adoc', \ 'rx': g:wiki#rx#link_adoc_xref_inline, \ 'rx_url': '\vim + + let g:wiki_link_default_schemes = { + \ 'wiki': { 'wiki': 'wiki', 'adoc': 'adoc' }, + \ 'md': 'wiki', + \ 'md_fig': 'file', + \ 'org': 'wiki', + \ 'adoc_xref_inline': 'adoc', + \ 'adoc_xref_bracket': 'adoc', + \ 'adoc_link': 'file', + \ 'ref_shortcut': '', + \ 'ref_definition': '', + \ 'date': 'journal', + \ 'cite': 'zot', + \} + *g:wiki_link_toggle_on_follow* This option allows disabling the toggle behaviour in |WikiLinkFollow| where "normal" text under the cursor is transformed into links. The behaviour is @@ -840,7 +869,7 @@ OPTIONS *wiki-config-options* \ 'adoc_xref_bracket': 'wiki#link#adoc_xref_inline#template', \ 'adoc_xref_inline': 'wiki#link#adoc_xref_bracket#template', \ 'date': 'wiki#link#wiki#template', - \ 'shortcite': 'wiki#link#md#template', + \ 'cite': 'wiki#link#md#template', \ 'url': 'wiki#link#md#template', \} @@ -1575,9 +1604,10 @@ specify global mappings available anywhere, and the liens annotated ============================================================================== LINKS *wiki-link* -Links are one of the most essential features of a wiki, and as such, require -particular attention. A link is a structure that consists of an URL (see -|wiki-link-url|) and a possibly empty description. +Links are one of the most essential features of a wiki. As such, it is +important to understand them. A link is a "structure" that consists of an URL +and a possibly empty description, e.g. the wiki link `[[URL]]`. The supported +link types are listed below. The mappings that act on links are listed in |wiki-mappings-default|. The most notable default mappings are: @@ -1590,50 +1620,170 @@ notable default mappings are: - `wf` can be used to transform a link between different types (see |g:wiki_link_toggles|). -These are the link formats that are currently supported with some examples: + *wiki-link-types* +These are the link types that are currently supported with some examples: -- Link URLs |wiki-link-url| - `http://www.example.com` - `wiki:index` - `journal:2013-04-05` - `doi:10.1002%2Fandp.19053220607` - Wiki links |wiki-link-wiki| `[[URL]]` `[[URL|Description]]` -- Markdown links |wiki-link-markdown| +- Markdown links |wiki-link-md| `[Description](URL)` -- Markdown image links |wiki-link-image| +- Markdown image links |wiki-link-md_fig| `![Caption text](URL)` -- Orgmode links |wiki-link-orgmode| +- Orgmode links |wiki-link-org| `[[URL]]` `[[URL][Description]]` -- Reference links |wiki-link-reference| +- Reference links |wiki-link-ref_shortcut| + |wiki-link-ref_definition| `[Target]` `[Description][Target]` -- Zotero shortlink |wiki-link-zotero| - `@citekey` -- AsciiDoc cross-reference links |wiki-link-adoc-xref| + `[Target]: URL` +- AsciiDoc cross-reference links |wiki-link-adoc_xref_bracket| + |wiki-link-adoc_xref_inline| `<>` `xref:URL[Description]` -- AsciiDoc link macro |wiki-link-adoc-link| +- AsciiDoc link macro |wiki-link-adoc_link| `link:URL[Description]` +- Cite links |wiki-link-cite| + `@citekey` +- ISO dates |wiki-link-date| + `2023-05-05` +- URLs |wiki-link-url| + `https://www.example.com` + +------------------------------------------------------------------------------ +WIKI LINKS *wiki-link-wiki* + +Wiki links are similar in style to the standard Mediawiki links. This is the +standard syntax for creating internal wiki links. The description part is +optional. Examples: > + + [[URL]] + [[URL|Description]] + +------------------------------------------------------------------------------ +MARKDOWN LINKS *wiki-link-md* + +Markdown links are one of the more common types of links. They look like +this: > + + [Description](URL) + +------------------------------------------------------------------------------ +MARKDOWN IMAGE LINKS *wiki-link-md_fig* + +Markdown image links are similar to markdown links: > + + ![Caption text](URL) + +------------------------------------------------------------------------------ +ORGMODE LINKS *wiki-link-org* + +Orgmode links look identical to wiki links if they don't have a description. +If they have a description, it is added within the outer square brackets +within a second pair of square brackers. Examples: > + + [[URL]] + [[URL][Description]] + +------------------------------------------------------------------------------ +REFERENCE LINKS *wiki-link-ref_shortcut* + *wiki-link-ref_definition* + +Reference style links are slightly different. They consist of up to three +parts: An optional `description`, a `label` and a `link definition.` The +syntax is best explained through an example: > + + The most simple form, and perhaps the most useful one, is to add a simple + reference like this [1]. + + One may also add a [description][label]. + + The target may consist of both words and numbers, e.g. [like this][Ref 3]. + + [1]: + [label]: + [Ref 3]: + +Reference links are implemented as two different link types: + +- `ref_shortcut`: matches links used in the text, such as `[1]` and + `[description][label]`. Following this link will either open the target URL + or move the cursor to the target URL. +- `ref_definition`: matches link targets, such as `[1]: URL`. Following this + will open the URL. + +------------------------------------------------------------------------------ +ASCIIDOC CROSS REFERENCES *wiki-link-adoc_xref_bracket* + *wiki-link-adoc_xref_inline* + +AsciiDoc cross-reference links or xrefs [0] look like this: > + + Bracket style + <> + <> + <> + <> + + Inline macro + xref:anchor[Description] + xref:filename.adoc#anchor[Description] + xref:[LONG URL][Description] + +The `[LONG URL]` variant is supported for cases where the filename contains +spaces. + +[0]: https://docs.asciidoctor.org/asciidoc/latest/macros/xref/ + +------------------------------------------------------------------------------ +ASCIIDOC LINK MACROS *wiki-link-adoc_link* + +The AsciiDoc link macro [0] is a generic link syntax that looks like this: > + + link:[] + +The `[]` will be recognized by wiki.vim as the link text. + +[0]: https://docs.asciidoctor.org/asciidoc/latest/macros/link-macro/ + +------------------------------------------------------------------------------ +CITE LINKS *wiki-link-cite* + +The cite links are a convenient link type that can be used with e.g. Zotero +URLs. That is, instead of writing a link with URL `zot:citekey` one may simply +write `@citekey`. + +See also |wiki-link-url| for more info on the Zotero URL scheme and handler. + +------------------------------------------------------------------------------ +ISO DATES *wiki-link-date* + +Dates written in ISO date format, e.g. 2023-05-05, will be recognized as +a link to `journal:2023-05-05`. ------------------------------------------------------------------------------ -LINK URLS *wiki-link-url* +URLS *wiki-link-url* -An URL, which is short for Uniform Resource Locator, has the general format +URL is short for Uniform Resource Locator and is an address to a resource. The +concept of URLs is specified in RFC 3986 "Uniform Resource Identifier (URI): +Generic Syntax" (https://datatracker.ietf.org/doc/html/rfc3986). - `[scheme:]address` - `` +A typical URL looks like this: `scheme:address`. Some example of URLs: -The `scheme` specifies which kind of link it is. When the URL is typed -directly and with a proper scheme, it will typically be possible to follow the -link directly without putting it inside a fuller link type. The scheme is -required in general. However, for some type of links, the scheme may be -implied by the link type. +- `http://www.example.com` +- `wiki:index` +- `journal:2013-04-05` +- `doi:10.1002%2Fandp.19053220607` -When the scheme is not specified for URLs inside one of the other link types, -then the `wiki` scheme is generally assumed (unless otherwise stated). +The `scheme` part specifies "which kind" of URL it is and is typically used to +identify which service should handle the URL. When the URL is typed directly +and with a proper scheme, it will typically be possible to follow the URL +directly without putting it inside a proper link type. However, if the +`address` part has spaces in it, the URL must be surrounded by angled +brackets, like this: ``. + +When the scheme is not specified for URLs inside a link, then the scheme is +specified from |g:wiki_link_default_schemes|. The following schemes are supported: @@ -1679,7 +1829,7 @@ The following schemes are supported: For more user flexibility, one can implement a custom file handler with |g:wiki_file_handler|. - This scheme is the default scheme for |wiki-link-image|. + This scheme is the default scheme for |wiki-link-md_fig|. doi ~ Will use the `generic` scheme handler on an expanded URL of the form @@ -1712,101 +1862,6 @@ Schemes are defined in `autoload/wiki/url/{scheme}.vim`, which means it is relatively easy to define new custom schemes. See the generic scheme for a simple example of how this is implemented. ------------------------------------------------------------------------------- -WIKI LINKS *wiki-link-wiki* - -Wiki links are similar in style to the standard Mediawiki links. This is the -main syntax for creating internal wiki links. The description part is -optional. Examples: > - - [[URL]] - [[URL|Description]] - ------------------------------------------------------------------------------- -MARKDOWN LINKS *wiki-link-markdown* - -Markdown links are one of the more standard types of links. They look like -this: > - - [Description](URL) - ------------------------------------------------------------------------------- -MARKDOWN IMAGE LINKS *wiki-link-image* - -Markdown image links are similar to markdown links: > - - ![Caption text](URL) - ------------------------------------------------------------------------------- -ORGMODE LINKS *wiki-link-orgmode* - -Orgmode links look identical to wiki links if they don't have a description. -If they have a description, it is added within the outer square brackets -within a second pair of square brackers. Examples: > - - [[URL]] - [[URL][Description]] - ------------------------------------------------------------------------------- -REFERENCE LINKS *wiki-link-reference* - -Reference style links are slightly different. They consist of up to three -parts: An optional `description`, a `label` and a `link definition.` The -syntax is best explained through an example: > - - The most simple form, and perhaps the most useful one, is to add a simple - reference like this [1]. - - One may also add a [description][label]. - - The target may consist of both words and numbers, e.g. [like this][Ref 3]. - - [1]: - [label]: - [Ref 3]: - -Reference style links may be followed with `` both on the reference -location and on the link line. - ------------------------------------------------------------------------------- -ZOTERO SHORTLINKS *wiki-link-zotero* - -As a minor convenience link type, Zotero URLs may be written in short as -`@citekey` instead of `zot:citekey`. See also |wiki-link-url| for more info on -the Zotero URL scheme and handler. - ------------------------------------------------------------------------------- -ASCIIDOC CROSS REFERENCES *wiki-link-adoc-xref* - -AsciiDoc cross-reference links or xrefs [0] look like this: > - - Bracket style - <> - <> - <> - <> - - Inline macro - xref:anchor[Description] - xref:filename.adoc#anchor[Description] - xref:[LONG URL][Description] - -The `[LONG URL]` variant is supported for cases where the filename contains -spaces. - -[0]: https://docs.asciidoctor.org/asciidoc/latest/macros/xref/ - ------------------------------------------------------------------------------- -ASCIIDOC LINK MACROS *wiki-link-adoc-link* - -The AsciiDoc link macro [0] is a generic link syntax that looks like this: > - - link:[] - -The `[]` will be recognized by wiki.vim as the link text. - -[0]: https://docs.asciidoctor.org/asciidoc/latest/macros/link-macro/ - ============================================================================== COMPLETION *wiki-completion* diff --git a/plugin/wiki.vim b/plugin/wiki.vim index f73e64d8..327d64c3 100644 --- a/plugin/wiki.vim +++ b/plugin/wiki.vim @@ -62,6 +62,19 @@ call wiki#init#option('wiki_link_creation', { \ 'url_extension': '', \ }, \}) +call wiki#init#option('wiki_link_default_schemes', { + \ 'wiki': { 'wiki': 'wiki', 'adoc': 'adoc' }, + \ 'md': 'wiki', + \ 'md_fig': 'file', + \ 'org': 'wiki', + \ 'adoc_xref_inline': 'adoc', + \ 'adoc_xref_bracket': 'adoc', + \ 'adoc_link': 'file', + \ 'ref_shortcut': '', + \ 'ref_definition': '', + \ 'date': 'journal', + \ 'cite': 'zot', + \}) call wiki#init#option('wiki_link_toggle_on_follow', 1) call wiki#init#option('wiki_link_toggles', { \ 'wiki': 'wiki#link#md#template', @@ -70,7 +83,7 @@ call wiki#init#option('wiki_link_toggles', { \ 'adoc_xref_bracket': 'wiki#link#adoc_xref_inline#template', \ 'adoc_xref_inline': 'wiki#link#adoc_xref_bracket#template', \ 'date': 'wiki#link#wiki#template', - \ 'shortcite': 'wiki#link#md#template', + \ 'cite': 'wiki#link#md#template', \ 'url': 'wiki#link#md#template', \}) call wiki#init#option('wiki_mappings_use_defaults', 'all') diff --git a/test/test-links/test-detection.vim b/test/test-links/test-detection.vim index b9aac75e..267f6db2 100644 --- a/test/test-links/test-detection.vim +++ b/test/test-links/test-detection.vim @@ -25,7 +25,7 @@ for s:lnum in range(18, 21) endfor let s:link = wiki#link#get_at_pos(23, 23) -call assert_equal('url', s:link.type) +call assert_equal('cite', s:link.type) call assert_equal('zot', s:link.scheme) let s:link = wiki#link#get_at_pos(23, 50) @@ -33,12 +33,12 @@ call assert_equal('url', s:link.type) call assert_equal('zot', s:link.scheme) let s:link = wiki#link#get_at_pos(24, 11) -call assert_equal('url', s:link.type) +call assert_equal('cite', s:link.type) call assert_equal('zot', s:link.scheme) call assert_equal('c1', s:link.key) let s:link = wiki#link#get_at_pos(24, 18) -call assert_equal('url', s:link.type) +call assert_equal('cite', s:link.type) call assert_equal('zot', s:link.scheme) call assert_equal('c2', s:link.key) diff --git a/test/wiki-adoc/index.adoc b/test/wiki-adoc/index.adoc index 900814b9..dcfc2413 100644 --- a/test/wiki-adoc/index.adoc +++ b/test/wiki-adoc/index.adoc @@ -14,3 +14,5 @@ xref:[foo bar.adoc][Foobar] Some text, cf. foo. +[[test]] +