Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Change link title based on note content #280

Closed
sadid opened this issue Mar 12, 2023 · 6 comments
Closed

[Feature Request] Change link title based on note content #280

sadid opened this issue Mar 12, 2023 · 6 comments

Comments

@sadid
Copy link

sadid commented Mar 12, 2023

When using wiki.vim or even plain Vim, links to notes are often created with the filename of the note as the title, such as [filename](filename.md). However, this can be suboptimal if the filename does not accurately reflect the content of the note. While I can use ci] to change the link title manually, it can be error-prone and with some hassle. To streamline this process, a keymap can call a function on current link and checks its content (e.g., by looking for a header), and replaces the link title with a more appropriate one.

I previously (before using any wiki) have written a basic function -- based on my limitd experience with vim script -- that did this under ,ct map.

Minimal working example

function! ExtractAndReplaceMDTitle()
    let current_col = col('.')
    let right_paren_col = searchpos(')', 'nc', '', current_col)[1]
    let left_bracket_col = searchpos('\[', 'bnc', '', current_col)[1]
    let markdown_link = getline('.')[left_bracket_col - 1 : right_paren_col]
    if markdown_link == ''
        echo 'No link found'
        return
    endif
    let file_path = substitute(markdown_link, '.*(\(.*\)).*', '\1', '')
    if !filereadable(file_path)
	echo 'File not found'
	return
    endif
    let header_regex = '^#\+\s\+\zs.*$'
    let lines = readfile(file_path)
    let new_title = ''
    for line in lines
        if line =~ header_regex
            let new_title = substitute(line, '^#\{1,6}\s*', '', '')
            break
        endif
    endfor
    if new_title == ''
        echo 'No header found'
        return
    endif
    let old_title = substitute(markdown_link, '.*\[\(.*\)\].*', '\1', '')
    let new_link = substitute(markdown_link, old_title, new_title, '')
    let current_line = getline('.')
    let new_line = substitute(current_line, '\[' . old_title . '\]', '[' . new_title . ']', '')
    if new_line == current_line
        echo 'No match found'
        return
    endif
    call setline('.', new_line)
endfunction

nmap <localleader>ct :call ExtractAndReplaceMDTitle()<CR>

This function works in a rudimentary way, but these days I'm enjoying wiki.vim and just wonder if possible to add such functionality with more robust support within wiki.vim instead. For example, if I could visually select all link in current note and press ,ct to update all titles in the selection.

@sadid sadid changed the title [Feature Request] Change link title based on note content (A rudimentary script is available) [Feature Request] Change link title based on note content Mar 12, 2023
@kosciak
Copy link

kosciak commented Mar 15, 2023

Have you tried plug>(wiki-link-extract-header) mapping and / or WikiLinkExtractHeader command? It sets link title to first header of linked wiki page.

@sadid
Copy link
Author

sadid commented Mar 16, 2023

Have you tried plug>(wiki-link-extract-header) mapping and / or WikiLinkExtractHeader command? It sets link title to first header of linked wiki page.

I must have been blind! I think I've looked into a wrong place. Also I had my own basic implementation of it which worked so ddidn't really look further. But Yes this works the as expected though on single link.

What I'm insterested in is a scaled version such that we visually select portion of the text and applying ,ct or :WikiLinkExtractHeader updated all selected links. Since not a pro vim dev, asking if such thing possible or straight-forward. The solution I come up with is to pass the visually selected test to a new function that filter out the detected links and apply this wiki#link#set_text_from_header() on each of them. However, I'm not sure if this plugin provide some sort of platform for doing such case?

@lervag
Copy link
Owner

lervag commented Mar 16, 2023

When using wiki.vim or even plain Vim, links to notes are often created with the filename of the note as the title, such as [filename](filename.md).

Let's focus on wiki.vim. I assume with "are often created", you mean e.g. when you do <cr> on top of a word?

However, this can be suboptimal if the filename does not accurately reflect the content of the note. While I can use ci] to change the link title manually, it can be error-prone and with some hassle.

Notice that wiki.vim also provides the text objects iu, it, and il (and a variants). E.g. ciu to change the url and cit to change the text.

To streamline this process, a keymap can call a function on current link and checks its content (e.g., by looking for a header), and replaces the link title with a more appropriate one.

@kosciak is right to mention WikiLinkExtractHeader; it seems relevant here.

…, but these days I'm enjoying wiki.vim and just wonder if possible to add such functionality with more robust support within wiki.vim instead.

I'm generally positive to adjust and further develop wiki.vim with new and improved features as long as I can see how it would be useful to me and/or the community.


What I'm insterested in is a scaled version such that we visually select portion of the text and applying ,ct or :WikiLinkExtractHeader updated all selected links. Since not a pro vim dev, asking if such thing possible or straight-forward. The solution I come up with is to pass the visually selected test to a new function that filter out the detected links and apply this wiki#link#set_text_from_header() on each of them. However, I'm not sure if this plugin provide some sort of platform for doing such case?

This should not be too hard. To be more precise, you want a visual version of WikiLinkExtractHeader that works on all links in the visual selection. Is that correct?

So, if I implemented the feature according to the following suggested documentation, you would have more or less what you want?

<plug>(wiki-link-extract-header)
WikiLinkExtractHeader
  Set link titles from the first header of the target file. In normal mode,
  this works on the link under the cursor. In visual mode, it works on all
  links in the current visual selection.

@sadid
Copy link
Author

sadid commented Mar 17, 2023

Let's focus on wiki.vim. I assume with "are often created", you mean e.g. when you do <cr> on top of a word?

I have lots of notes created before use of wiki.vim and while the filenames is not completely random, they're more suited to find than description of the content. Even with help of <CR> in wiki.vim, I often find myself prefer changing the note name to be consistent with the existing ones. In some workflows people even create ranodm filenames or time-id based filenames, so in those workflows the default title (=filenme) need to be changed.

I'm compeltely agree on all other points.


To be more precise, you want a visual version of WikiLinkExtractHeader that works on all links in the visual selection. Is that correct?

So, if I implemented the feature according to the following suggested documentation, you would have more or less what you want?

<plug>(wiki-link-extract-header)
WikiLinkExtractHeader
  Set link titles from the first header of the target file. In normal mode,
  this works on the link under the cursor. In visual mode, it works on all
  links in the current visual selection.

Yes exactly, that's perfectly targets what I wanted.

@lervag
Copy link
Owner

lervag commented May 18, 2023

Sorry for taking so long! I've implemented a first version now in #306; I'll merge when I've added tests (and fixed possibly discovered bugs). I'll close the issue here; feel free to continue discussion or add comments to #306.

@lervag lervag closed this as completed May 18, 2023
lervag added a commit that referenced this issue May 18, 2023
lervag added a commit that referenced this issue May 18, 2023
@lervag
Copy link
Owner

lervag commented May 18, 2023

There, I've merged #306 - I believe the feature should work as expected now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants