Is this linking by hand something I alone want?

In the course of writing, I will often spot a word or phrase that I know is an alias (call it thealias) to another file (thefile) in my vault, select it, and hit [[ expecting this to turn it into a link to the thefile , but instead this results in a link to a non-existent file thealias.

The same word or phrase, thealias, is shown in the Unlinked Mentions as a possible link to thefile. So a workaround is close at hand, but I would still like to have the option of selecting and linking thealias by hand, so to speak, hitting [[.

Am I overlooking something? If not, should I perhaps make this a feature request?

This could be a nice feature request.

What is currently working:

If you start writing an internal link with the alias text, the true destination (“thefile”) is proposed as link destination. Thus, if you start typing [[theali , a link to “thefile” will be proposed, if you now hit the enter key, the resulting link will look like this: [[thefile|thealias]].

Thus, the only current workaround to your use case (besides using the Outgoing links/unlinked mentions option) would be:

If you have some text:

Some text bla bla thealias bla bla, you could select the word “thealias”, hit [[ in order to surround it with square brackets, and as soon as you delete the last letter (the “s”), the destination link “thefile” is instantly proposed, then you can hit “enter”.

Maybe not ideal compared to your proposition, but an alternative idea that might help for the moment and might be easier/faster to implement than searching under the outgoing links section each time.

As a proof of concept I present to you a template which scans through all aliases, and if the selected text starts with the selected text, it inserts an link to that file using the alias. If multiple options are present it allows you to choose which file you want to link to.

Currently it does not match against actual file name, it’s just for the aliases. It also lists the full file path in parentheses in case you’ve got multiple notes with the same name. This could of course be adapted to your liking.

To use this template, insert the code in the section below into a template in your template folder.

The actual template

Insert the following into a template in your template folder:

<%*
const dv = app.plugins.plugins.dataview.api

// Bail out if nothing is selected
const selection = tp.file.selection()
if ( selection == "" ) {
  alert("Please select some alias text before inserting template")
  return
}

// Build the two lists, file path vs alias,
const pathToAliases = {} // file.path to alias(es)
const aliasToPaths = {}  // alias to file.path(s)
await dv.pages()
  .where(p => p.file.aliases.length > 0)
  .forEach(p => {
    pathToAliases[p.file.path] = p.file.aliases
    p.file.aliases.forEach( a => {
      if ( !(a in aliasToPaths ) ) 
        aliasToPaths[a] = []
        
      aliasToPaths[a].push(p.file.path)
    })
  })

// Look through the alias, and pick any alias
// which starts with the pre-selected text
// Can be changed by changing the `k.startsWith()`
const suggestions = []
Object.keys(aliasToPaths)
  .filter(k => k.startsWith(selection))
  .forEach(a => {
    aliasToPaths[a].forEach( p => {
      suggestions.push([a, p, a  + " (" + p + ")"])
    } )
  }) 

// Build a suitable link based on alias matching
// the selected text. If only suggestion is available
// return directly, and ask the user if multiple aliases
// are possible
if ( suggestions.length == 0 ) {
  // No matching aliases found
  alert("No matching aliases was found. Will return selected text")
  tR = selection

} else if ( suggestions.length == 1 ) {
  // Single suggestion found, return directly
  tR += dv.fileLink(suggestions[0][1], false, suggestions[0][0])
  
} else {
  // Multiple suggestion, ask user which to use
  const response = await tp.system.suggester(t => t[2], suggestions, false, "Choose alias")
  if ( !response ) 
    tR = selection
  else
    tR = dv.fileLink(response[1], false, response[0])
}
_%>
A short explanation of the template

The template starts by checking that you’ve actually selected some text, and gives a warning if not, and bails out of any further processing. Keeping the selection as it was.

The template then loops through all pages to gather all the aliases, and restructure them into two variables, pathToAliases and aliasToPaths. The first is ignored in this settings, but could possible be useful in other settings. The second is the one we use to search for possible matches in.

And that search is the next step, where we try to match the alias against the selection text. I’ve opted for using k.startsWith() which matches the selection against the start of the alias key (k). This can of course be changed to whatever variant of matching you want. Like in-case sensitive matches, or whether the selection is just somewhere within the alias, and so on.

To differentiate between re-used aliases, the full file path of the file holding the aliases is inserted into the suggestions list. This could possibly be ignored, or used in a secondary suggester if needed. Or one could adapt this to show only the file name or similar stuff. For this proof of concept I included the full file path.

After building the suggestions list, it’s checked against the length, as if there are no matches, it gives a warning and returns the selection text. If there is only match in the aliases, it returns the proper link with the alias. And finally if multiple matches was found, it asks the user which of the matches to use before inserting that link into the document.

After inserting the template, go to Settings > Templater > Template Hotkeys, and hit the Add new hotkey for template. Select your newly created template in the first box, and hit the plus icon, which sends you to the hotkey settings. Select your template, and hit the plus icon and select a key combination of your choice.

Now you should be ready to select thealias, and hit your key combination and let the magic unfold.

2 Likes

Thank you, I’ll give this a try!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.