Closed Konfekt closed 5 months ago
Thanks for sharing this snippet.
I had some trouble getting it to work:
E216: No such group or event: vimrcFileTypeGitcommit BufWrite <buffer> TagLinks | call mdlink#ConvertAllLinks() | call PutLinksBeforeComments()
I am not very familiar with autocmd
s, but changing it this way made it work on my system (I am using Neovim):
augroup git_links
autocmd!
autocmd FileType gitcommit autocmd BufWrite *
\ TagLinks |
\ call mdlink#ConvertAllLinks() |
\ call PutLinksBeforeComments()
augroup END
Could you explain the purpose of TagLinks
?
Integrating this into the main plugin seems difficult, but these extensions are certainly welcome. The Wiki should now be open for everyone. I could also mention extensions like this one and the one you shared in #1 in README.md
.
I am sorry, the autocmd group vimrcFileTypeGitcommit
is a personal leftover, there would be a preceding buffer-local augroup definition like
augroup vimrcFileTypeGitcommit
autocmd! * <buffer>
augroup END
The idea of Taglinks is to convert all https into markdown links, so that your plug-in can treat them.
One motiviation of using your plug-in is that sometimes one lazily pastes long https into a message, but these better be put at the end, and some reference inline.
By the way, the wiki does not yet show up here
The Wiki should now be up and running and editable by everyone. I have created blank pages for email and git commit extensions. Feel free to add your scripts, as you are familiar with them.
I don't really use Vim for email, so I am unable to test the snippet you shared in #1.
This extension works nicely though.
I like the idea of TagLinks
. It appears to add an unnecessary dot, e.g. [vim.](https://vim.org)
.
It should probably be noted that users have to add this script to gitcommit.vim
, instead of vimrc
, to avoid that autocmd BufWrite <buffer>
would operate on all filetypes.
Oops, you are right, I fixed the regex above. The command now reads
command! -buffer -range=% -bar TagLinks silent keeppatterns <line1>,<line2>substitute#\v%(\[[^\]]+\]\(\s*)@<!\zs<https?://(%([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,})#[\1](\0)#giep
I think it does not hurt to provide sensible stubs to other common text ftplugins. Maybe Taglinks (corrected) can be added generically? I think this preprocessing is what https://github.com/qadzek/vim-md-link/issues/1 has in mind, and also what sprang to mine when I heard of your plug-in
The Wiki should now be up and running and editable by everyone. I have created blank pages for email and git commit extensions. Feel free to add your scripts, as you are familiar with them.
I updated the wiki accordingly, including a speculative declaration of b:md_link_heading
I think it does not hurt to provide sensible stubs to other common text ftplugins. Maybe Taglinks (corrected) can be added generically?
This is certainly a good idea, to make it easier for users to create new extensions.
Currently, TagLinks
converts
GitHub is a website https://github.com
to
GitHub is a website [github.com](https://github.com)
That is already a nice addition. However, running this plugin leaves us with:
GitHub is a website [github.com][0]
## Links
[0]: https://github.com
While, correct me if I am wrong, what we really want is the following,
because that [github.com]
is a bit ugly?
GitHub is a website [0]
## Links
[0]: https://github.com
So, in my opinion, the plugin should first be able to convert [github.com](https://github.com)
into [0]
instead of [github.com][0]
.
Yes, at the moment it works as described in the README
# Notes
[Vim](https://www.vim.org) and [Neovim](https://neovim.io) are text editors.
will be turned into
# Notes
[Vim][0] and [Neovim][1] are text editors.
## Links
[0]: https://www.vim.org
[1]: https://neovim.io
But true, in text messages, like mail, gitcommits, ..., more common is a simple bracketed number.
So the taglinks preprocesses the links for md-link.
You propose a command to postprocess them, removing the tag? I have not so strong opinions on it; the domain name can make the text more readable
So the taglinks preprocesses the links for md-link.
You propose a command to postprocess them, removing the tag? I have not so strong opinions on it; the domain name can make the text more readable
When the feature request about email was made in #1, I was thinking about adding a new syntax, but that would be quite hard to implement.
Your idea seems more straightforward:
1) Preprocess: :TagLinks
2) Main conversion: :MdLinkConvertAll
3) Postprocess: optional, no command yet
Take a look at the latest wiki modifications; it was a bit of work to make it work
Take a look at the latest wiki modifications; it was a bit of work to make it work
I would add a bit more explanation about what your snippets are doing exactly and maybe include a before/after comparison like in README.md
, so it will be easier to understand for new users.
Maybe this plugin should include something like let b:md_link_insert_heading_before_first = '#'
, so PutLinksBeforeComments()
wouldn't be needed.
In both snippets, there is a hardcoded heading value in let links_start = search('^## Links$', 'nW')
.
In both snippets, there is a hardcoded heading value in let links_start = search('^## Links$', 'nW').
Thank you very much, I missed updating the function
Maybe this plugin should include something like let b:md_link_insert_heading_before_first = '#', so PutLinksBeforeComments() wouldn't be needed.
Yes, an end marker would be great
It would nice if your range function takes as optional parameters beginning and end markers, say.
I am not sure if this is what you mean, but I changed the plugin in a way that the reference section is no longer necessarily at the end of the buffer. This should simplify creating extensions a lot.
The code is still experimental (no documentation), so I created a dev
branch. Would you be willing to give it a try?
You would use it like this:
" mail.vim
if !empty(findfile('ftplugin/markdown/vim-md-link.vim', &runtimepath))
runtime ftplugin/markdown/vim-md-link.vim
endif
if exists(':MdLinkConvertAll') != 2 | finish | endif
let b:md_link_heading = 'Links:'
let b:md_link_heading_before = '^--'
and
" gitcommit.vim
if !empty(findfile('ftplugin/markdown/vim-md-link.vim', &runtimepath))
runtime ftplugin/markdown/vim-md-link.vim
endif
if exists(':MdLinkConvertAll') != 2 | finish | endif
let b:md_link_heading = 'Links:'
let b:md_link_heading_before = '^# Please enter'
Note that for now, only inline Markdown links are supported [foo](https://bar.com)
. I will work on preprocess and postprocess commands though.
There is now also an IRC channel: #vim-md-link on Libera.
Yes, seems to work:
[github.com][1]
[github.com][0]
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
[github.com][2]
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.
Links:
[0]: https://github.com/qadzek/vim-md-link/issues/5
[1]: https://github.com/qadzek/vim-md-link/issues/5
[2]: https://github.com/qadzek/vim-md-link/issues/5
--
Signature
using
let b:md_link_heading = 'Links:'
let b:md_link_heading_before = '^-- $'
let s:body_range = '1/^\s*$/,/' . b:md_link_heading_before.'\|^\V'.escape(b:md_link_heading,'\').'\m' . '$/-1'
command! -buffer -range=% -bar TagLinks silent keepjumps keeppatterns <line1>,<line2>substitute#\v%(\[[^\]]+\]\(\s*)@<!\zs<https?://(%([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,})\S+#[\1](\0)#giep
autocmd BufWrite <buffer>
\ exe s:body_range . 'TagLinks'|
\ exe s:body_range . 'MdLinkConvertRange'
For gitcommit less so:
[github.com][0]
# Immetti il messaggio di commit per le modifiche. Le righe che iniziano
# con '#' saranno ignorate e un messaggio vuoto interromperà il commit.
#
# Sul branch master
# Il tuo branch è aggiornato rispetto a 'origin/master'.
#
# Modifiche di cui verrà eseguito il commit:
# modificato: .vim/ftplugin/gitcommit_md-link.vim
#
# ------------------------ >8 ------------------------
Links:
[0]: https://github.com/qadzek/vim-md-link/issues/5
using
let b:md_link_heading = 'Links:'
let b:md_link_heading_before = '^#'
let s:body_range = '1,/' . b:md_link_heading_before.'\|\V\^'.escape(b:md_link_heading,'\') . '\$/-1'
command! -buffer -range=% -bar TagLinks silent keepjumps keeppatterns <line1>,<line2>substitute#\v%(\[[^\]]+\]\(\s*)@<!\zs<https?://(%([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,})\S+#[\1](\0)#giep
command! -buffer -range=% LinkConvertRange <line1>,<line2>TagLinks | <line1>,<line2>MdLinkConvertRange
autocmd BufWrite <buffer> exe s:body_range..'LinkConvertRange'
I should have given a bit more explanation. let b:md_link_heading_before
searches from the bottom of the buffer until the first match for the pattern is found.
So I would give let b:md_link_heading_before = '^# Immetti
a try, because that's unique; there are multiple occurrences of '^#'
.
Oh, that's good to know. Yes, that works.
Thanks for testing the new features.
I have just added three new commands:
MdLinkPreProcessUrls
: based on your TagLinks
commandMdLinkPostProcessUrls
: remove [foo]
from [foo][5]
MdLinkProcessConvert
: pre-process, then convert all, then post-processThe first two are mostly helper commands, you probably want to use the last one.
Plaintext URLs like foo https://bar.com
are now supported. This should simplify your extensions by a lot.
That's great. Would you mind passing a range to MdLinkProcessConvert? For example, to spare links in the mail header. Also in Git commit only up to the first comment. So the s:body_range
still has its use.
Also, how about allowing concatenating commands by adding -bar
to their definition ?
Also, how about allowing concatenating commands by adding -bar to their definition ?
Should this be added to every command? Thanks for the suggestion, I wasn't really aware of -bar
.
That's great. Would you mind passing a range to MdLinkProcessConvert? For example, to spare links in the mail header. Also in Git commit only up to the first comment. So the s:body_range still has its use.
I could make both mdlink#ProcessUrls()
and mdlink#ProcessConvertRange()
range functions, but the latter calls the former and I am not sure how to pass a range from one function to another?
Should this be added to every command? Thanks for the suggestion, I wasn't really aware of -bar.
Yes, indeed
I am not sure how to pass a range from one function to another?
Does
function! FirstFunction(...) range
" Capture the range into variables
let l:startline = a:firstline
let l:endline = a:lastline
" Do something with the range, if needed
" ...
" Call the second function with the range
execute l:startline.','.l:endline.'call SecondFunction()'
endfunction
function! SecondFunction() range
" This function now has access to the range
" Do something with the range
for i in range(a:firstline, a:lastline)
" Process each line
" ...
endfor
endfunction
help?
Thank you. execute l:startline.','.l:endline.'call SecondFunction()'
was crucial to getting this right.
You can now use any of these commands. For convenience, I created an All
version for every range function.
MdLinkPreProcessUrls
MdLinkPostProcessUrls
MdLinkProcessConvert
MdLinkPreProcessUrlsAll
MdLinkPostProcessUrlsAll
MdLinkProcessConvertAll
Let me know if it works as expected for gitcommit
, mail
or other non markdown
filetypes.
Yes, it works flawlessly, thank you very much. I updated the wiki accordingly.
Maybe in the future, comments could be skipped, say by an exclusion regex ^>
.
For example, in a mail, one rarely wants to reference all the URLs in the cited text. One can restrict the range to the first citation, but maybe the text continues afterward:
[0]
John Doe said:
>
> [1]
Links:
[0]: https://github.com/qadzek/vim-md-link/tree/dev
[1]: https://github.com/qadzek/vim-md-link/tree/main
I updated the wiki accordingly.
Thanks. I am not sure if let s:body_range
still needed, in both extensions?
And for ft=gitcommit
, is PutLinksBeforeComments()
still required? let b:md_link_heading_before
should take care of that part.
Maybe in the future, comments could be skipped, say by an exclusion regex ^>.
I will try to add that, but I will focus first on writing tests and documentation for the recently added features.
I am not sure if let s:body_range still needed, in both extensions?
Yes, for the mails only the links in the body need conversion, not in the subject header say. For commits, not those in comments.
And for ft=gitcommit, is PutLinksBeforeComments() still required? let b:md_link_heading_before should take care of that part.
As you explained above, b:md_link_heading_before
looks from below, but the links are placed before the comments
Yes, for the mails only the links in the body need conversion, not in the subject header say. For commits, not those in comments.
Oh, I see. I didn't realize there could be links in the subject header or in the comments.
Maybe in the future, comments could be skipped, say by an exclusion regex ^>.
Thank you for the suggestion. This feature has now been implemented. See :help b:md_link_skip_line
for the details.
I have also performed several refactorings, to remove code duplication, and have added tests and documentation for the new features.
If you don't notice any bugs, I will merge it into main
.
Great! I'll use this starting from now.
b:md_link_skip_line
You could suggest, or even default to, &commentstring
I am trying
let b:md_link_skip_line = '\V\^'..substitute(escape(&commentstring,'\'),'%s','\\.\\*', 'g')..'\$'
Seems a sensible default
let b:md_link_skip_line = '\V\^'..substitute(escape(&commentstring,'\'),'%s','\\.\\*', 'g')..'\$'
Seems a sensible default
Thanks for the suggestion. This has now been implemented: 1764dbc7d7f9842719574340c6642b5994797722
the setup lines are becoming fewer
That was the goal :smile: Now it should be pretty easy to extend this plugin to other filetypes.
This has now been implemented: https://github.com/qadzek/vim-md-link/commit/1764dbc7d7f9842719574340c6642b5994797722
While this is a good default, it is not perfect, as the commentstring uses spacing after the comment sign in, say shell or mail (and likely many other) files, and thus does not recognize, say ##
or >>
.
Since most likely no comment signs depend on white space, maybe just strip the space before %s
to make it more robust.
There are tests for JavaScript comments // foo
and Markdown comments <!-- bar -->
and your regex seems to be able to handle both.
Yes, that will work. But ///
will not work for Javascript, though still a comment. Well, it's a finesse, but I doesn't cost much calling substitute(b:md_link_skip_line, '\s', '', g)
I wasn't entirely happy with the pre- and post-processing. It was working alright for converting links, but it wasn't compatible with :MdLinkPeek
, :MdLinkJump
, :MdLinkOpen
and :MdLinkDelete
. So I have removed the pre- and post-processing commands in the dev
branch and added native support for plaintext links. Note that this is a breaking change. Would you be willing to give it a try?
Surely, but what do I have to try, and what to change? I am mainly using mdlink as documented in the wiki
Maybe you could indicate how the wiki needs to be updated?
Surely, but what do I have to try, and what to change? I am mainly using mdlink as documented in the wiki
Just your normal workflow, e.g. converting links in a gitcommit
buffer. You can give :MdLinkPeek
, :MdLinkJump
, :MdLinkOpen
and :MdLinkDelete
a try, these should now work in non-Markdown documents too.
Maybe you could indicate how the wiki needs to be updated?
MdLinkProcessConvert
has been removed, so it should be replaced in your snippets, both in the if exists
and in the autocmd
. You are converting a range (s:body_range
), so you should be able to replace it by MdLinkConvertRange
.
And MdLinkDeleteUnneededRefs
has been renamed to MdLinkDelete
.
MdLinkProcessConvert has been removed, so it should be replaced in your snippets, both in the if exists and in the autocmd. You are converting a range (s:body_range), so you should be able to replace it by MdLinkConvertRange.
Okay, so MdLinkProcessConvert
is now MdLinkConvertRange
? Feel free to adapt the Wiki
I have updated the Wiki. I also had to change your aliases a bit. I can't really test those because I don't use aliases.
Okay, so
MdLinkProcessConvert
is nowMdLinkConvertRange
?
Before, only Markdown inline links [foo](http://bar.com)
were supported. To handle plaintext links like foo http://bar.com
, in e.g. gitcommit
buffers, these plaintext links had to be pre-processed to Markdown links, then converted and afterwards needed post-processing.
Now, plaintext links are natively supported. This means all commands and functions related to pre- and post-processing have been removed. This is a breaking change.
MdLinkConvertRange
exists to convert the links contained in a range of lines. To convert only a link on the current line, you might prefer MdLinkConvertSingle
. Or, to convert the entire buffer, MdLinkConvertAll
.
Okay, thank you. This is on the dev branch that I will switch to using your adaptions of the wiki.
I will merge it into main if you don't notice anything weird. All features should now be available for both Markdown buffers and for other filetypes.
I will try to implement #6 next.
Thanks for testing the plugin.
:MdLinkDelete
has been replaced by :MdLinkReformat
(another breaking change).
This new command is pretty powerful. It's especially useful for long documents, containing lots of links. It can renumber, merge and delete links. :help :MdLinkReformat
contains some examples.
I have updated the Wiki accordingly.
There is another major update, once again including some breaking changes (hopefully for the last time). It's available on the main
branch.
I wanted to make the plugin more user-friendly, for newcomers to the plugin and for people not so experienced with Vim.
I wasn't entirely happy with the way the key bindings were set and the way to activate the plugin for additional filetypes, so I have made these changes:
There are still no mappings built-in to avoid conflicts with existing key bindings, but the user can try the suggested key bindings simply by setting let g:link_use_default_mappings = 1
in their vimrc. It's still possible to specify your own mappings.
I converted the plugin from a ftplugin
plugin to a general one, so the user no longer has to create files like ~/.vim/ftplugin/mail.vim
. Now, they can set e.g. let g:link_enabled_filetypes = ['mail', 'gitcommit', 'markdown']
to specify for which filetypes the plugin should be activated. I implemented this using autocmds; I am not really sure if that was the best approach.
I renamed the plugin as well, to less emphasize the Markdown part: it's now link.vim
. And for filetypes other than Markdown, Links:
is now the default heading, instead of ## Links
. The Wiki has been updated.
Thank you for the heads-up. All the changes seem sensible. I hope to have caught all affected places in my local config
Regarding the autocmd, it looks fine, but somehow fires later than defining it in a ftplugin file.
Therefore the previous check for the existence of :Link
command became for the default file types
if !exists('g:loaded_link') | finish | endif
if exists('g:link_enabled_filetypes') && index(g:link_enabled_filetypes, &l:filetype) == -1 | finish | endif
respectively for the others
if !exists('g:link_enabled_filetypes') || index(g:link_enabled_filetypes, &l:filetype) == -1 | finish | endif
I am not really sure how to implement your two snippets.
Regarding the autocmd, it looks fine, but somehow fires later than defining it in a ftplugin file.
I did notice that e.g. when opening foo.py
and executing :set ft=markdown
, the plugin isn't working, while I expected the autocmd would fire. Not sure if that's related.
if !exists('g:link_enabled_filetypes') || index(g:link_enabled_filetypes, &l:filetype) == -1 | finish | endif
g:link_enabled_filetypes
not existing is allowed. Currently, if the user doesn't set g:link_enabled_filetypes
, the plugin will be activated for the default filetypes: let s:default_enabled_filetypes = [ 'markdown', 'vimwiki', 'mail', 'text' ]
.
g:link_enabled_filetypes not existing is allowed. Currently, if the user doesn't set g:link_enabled_filetypes, the plugin will be activated for the default filetypes: let s:default_enabled_filetypes = [ 'markdown', 'vimwiki', 'mail', 'text' ].
Exactly, that's why for these filetypes additional checks are needed, as implemented above.
did notice that e.g. when opening foo.py and executing :set ft=markdown, the plugin isn't working, while I expected the autocmd would fire. Not sure if that's related.
That must be a separate issue; for me on Ubuntu 22.04 with 9.1.369 it fires when switching, say from TomL files.
I am not really sure how to implement your two snippets.
These are maybe useful for the snippets in the wiki, but now seem overkill
That must be a separate issue; for me on Ubuntu 22.04 with 9.1.369 it fires when switching, say from TomL files.
It seems to fire on my system now too. Strange.
These are maybe useful for the snippets in the wiki, but now seem overkill
Ok. Feel free to make a PR if you feel otherwise.
I will close this issue, as it's getting long and the original issue has been solved. Don't hesitate to open a new one if anything comes up. Thanks again for your suggestions.
For what it's worth (maybe put it in a wiki?), here's an adaption to gitcommit messages, moving the links into a link section before any other comments on writing the buffer: