Return links/Back links

@brookter, here is a script that should work. Let me know how it goes.

EDITED: See version C above

I shall indeed! Thanks very much, Bernado. I really appreciate it.

1 Like

Yes, that seems to work without any problems.

Muito obrigado!

EDIT: I only had a quick glance at the script before, but now I’ve had a longer look I see you went to the trouble of changing the type of links to [[link]] and removing the unnecessary (for me) options as well!

That really is very kind of you to take so much trouble. Thanks again!

1 Like

@Bernardo_V, this is extremely useful. I’ve been able to get it to work as a stand alone script that I can trigger with a hot key from Keyboard Maestro.

However, I cannot get it to fully work when I set it up as a smart rule. Something happens as I see a new “Returnlinks” section added to the Custom Inspector, but it doesn’t get populated. @brookter what did you change to make it work?

I didn’t have to change anything to get it to work – that is, if you’re talking about the SmartRules specific code Bernado did for me, not the original V2.

I think Bernado himself made some changes (very kindly) from V2 though - the smart rule question doesn’t ask any questions, and it’s set to add the links to the end of the document itself, not to a custom field (which I don’t use).

If you’re using different settings for the V2 script, then perhaps that’s the issue?

I just updated the first two posts.
Take a look at version A.2 above and let me know if this is the one you were looking for :wink:

1 Like

Boom - that worked! Thank you - this is really awesome. I’m setting up the Smart Rule to work manually once for all my notes, and then have it set to trigger upon saving.

Edit: actually, scratch that - I’ve set up a single Smart Rule to trigger upon opening. It’s much smoother.


Wow Bernardo. That is so cool! Thanks very much. Also, I have read about your work on Aristotle the other thread you did. Its great to see how so many people who work in such a wide variety of fields are able to bend this application to their needs. Thanks for sharing, this is great.

1 Like

This is the last version of script A.2

  • "RegexAndStuffLib" is no longer needed.
  • No need to add database UUID.
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

property UseAliases : true
property theFont : "" -- Your favorite font
property MDField : "" -- Custom meta data field name

on performSmartRule(theSources)
	tell application id "DNtp"
		show progress indicator "Updating return links"
		--	set theSources to the selection
		repeat with theSource in theSources
			set theSearchString to my prepare_search_string(theSource)
			set theName to name of theSource
				set theShortName to texts 1 through 4 of theName
			on error
				set theShortName to texts 1 through 3 of theName
			end try
			set theShortName to my replaceText(theShortName, " ", "%20")
			set theList to my get_list(theSearchString, theShortName)
			set theResult to my print_to_DT(theList, theSource)
		end repeat
		hide progress indicator
		display notification "return links updated"
	end tell
end performSmartRule

-- Handlers section

on replaceText(theString, old, new)
	set {TID, text item delimiters} to {text item delimiters, old}
	set theStringItems to text items of theString
	set text item delimiters to new
	set theString to theStringItems as text
	set text item delimiters to TID
	return theString
end replaceText

on trimtext(theText, theCharactersToTrim, theTrimDirection)
	set theTrimLength to length of theCharactersToTrim
	if theTrimDirection is in {"beginning", "both"} then
		repeat while theText begins with theCharactersToTrim
				set theText to characters (theTrimLength + 1) thru -1 of theText as string
			on error
				-- text contains nothing but trim characters
				return ""
			end try
		end repeat
	end if
	if theTrimDirection is in {"end", "both"} then
		repeat while theText ends with theCharactersToTrim
				set theText to characters 1 thru -(theTrimLength + 1) of theText as string
			on error
				-- text contains nothing but trim characters
				return ""
			end try
		end repeat
	end if
	return theText
end trimtext

on sortlist(theList)
	set theIndexList to {}
	set theSortedList to {}
	repeat (length of theList) times
		set theLowItem to ""
		repeat with a from 1 to (length of theList)
			if a is not in theIndexList then
				set theCurrentItem to item a of theList as text
				if theLowItem is "" then
					set theLowItem to theCurrentItem
					set theLowItemIndex to a
				else if theCurrentItem comes before theLowItem then
					set theLowItem to theCurrentItem
					set theLowItemIndex to a
				end if
			end if
		end repeat
		set end of theSortedList to theLowItem
		set end of theIndexList to theLowItemIndex
	end repeat
	return theSortedList
end sortlist

on prepare_search_string(theSource)
	tell application id "DNtp"
		set theName to name of theSource
		set theNameString to "(\"" & theName & "\")"
		set theDB to the name of current database
		set theAliases to ""
		if UseAliases then set theAliases to aliases of theSource
		if theAliases is not "" then
			set theAliasesString to my trimtext(theAliases, ", ", "end")
			set theAliasesString to my trimtext(theAliases, " ", "end")
			set theAliasesString to my replaceText(theAliasesString, ", ", "\") OR (\"")
			set theSearchString to theNameString & " OR " & "(\"" & theAliasesString & "\")"
		end if
		if theAliases is "" then
			set theSearchString to theNameString
		end if
		set theSearchString to "name!=" & theName & " content: " & theSearchString & space & "kind: markdown"
		return theSearchString
	end tell
end prepare_search_string

on get_list(theSearchString, theShortName)
	tell application id "DNtp"
		set theRecords to search theSearchString in current database
		set theNR to count theRecords
		--	log message "Found " & theNR & " return links to the record"
		set theList to {}
		repeat with each in theRecords
			set the end of theList to return & quoted form of ("<a id=" & name of each & "\" href=\"" & reference URL of each & "?search=" & theShortName & "&reveal=1" & "\">" & name of each & "</a></br>")
		end repeat
		considering numeric strings
			set theList to my sortlist(theList)
		end considering
		return theList
	end tell
end get_list

on print_to_DT(theList, theSource)
	tell application id "DNtp"
		set theList to "'<font size=\"6\" color=\"#8080BB\"><font face=\"" & theFont & "\">'" & theList & "'</font></font>'"
		-- Convert to RTF
		set theRTF to (do shell script "echo " & theList & " | textutil -stdin -stdout -inputencoding utf-8 -format html -convert rtf | pbcopy")
		set theRTF to the clipboard
		set theRTF to «class RTF » of theRTF
		add custom meta data theRTF for MDField to theSource
	end tell
end print_to_DT

@rlamber3, thank your for your kind words :wink:
Jim @BLUEFROG, is there some restriction against editing older posts? I tried to edit the original post but couldn’t do it.

No restriction I’m aware of at this time.

1 Like

@Bernardo_V, I’d like to thank you for offering these scripts to us. Your generosity helps those of us unfamiliar with scripting.

I had a question regarding Version C and A2. I searched for the Regex lib, but i received a 404 error from the Mac Automation website. Then I noticed, in Version A2, you somehow you removed the need for the regex lib altogether. I’m curious, how would one update Version C in a similar manner?

I’m attempting to alter your script to append backlinks to the file. While your A2 script works flawlessly, I think having backlinks appended to a note is be a better long term solution. I have been unsuccessful in combining C and A2 into a workable script.

What do you think? Is such an edit to Version C possible? And if so, how?

Hi @biznachio, welcome

You can remove the reference to the script library without any problems in version C. I just did that and added some improvements. Here is the updated version.

Thank you very much for posting these scripts @Bernardo_V.
I am trying to leverage the new version you shared with @biznachio.

So I created two test files 1 and 2. And File links to

I selected

property AutoWiki_Links : false

… as I use wiki-links.

Based on my understanding the smart-rule script should create a backlink in file pointing back to

But this does not seem to work for me. What do i miss?

Thank you very much for your amazing work across this forum.

hi @jooz, you’re welcome. I just fixed the script. Let me know if it works alright for you.

For the last version of the scripts posted to this thread, please see this repository:

Thank you very much.

I am leveraging Version A as a smart rule.

With Autowikilinks false

The script is stuck for me in step 2:
and I cannot seem to cancel this action (requires closing DT).
Logs say theText is not definied:

Seems to work fine here. Is this the script you are using? Have you tried adding a condition to the smart rule so that it will only target plain text files?

I am late to this thread, so have only used the latest scripts from GitHub as of today. I am seeing the same message in the log: “on performSmartRule the variable theText is not defined”

I am using version A unchanged.

Using Script Debugger, I set a breakpoint at
tell application id “DNtp”
just inside performSmartRule() but it never triggers.

I have run standalone scripts in DT3 but this is my first attempt with a script in a smart rule so I am probably not understanding something fundamental.

I have tried the smart rule only targeting plain text and or markdown files with the same result as any document.

Hope this helps shed some light on the situation.

Hello and thank you again @Bernardo_V. Your script works like a charm! I am indebted to you.

I am curious, is there a way to skip adding the backlink delimiter on notes where if the list is empty? That way, only files with backlinks get parsed and the others don’t have a Backlinks heading with no links listed beneath.

@Bernardo_V - Thanks for these scripts!

Today, I set up a small framework to debug the script following Jim’s (@BLUEFROG) suggestion: How best to debug Applescripts running inside DT3

That quickly showed me that the reason why I was getting “theText is not defined” message in the log is because one of my test files was empty. It was being linked to from another file, but there was no text inside this “target” file and that was causing the error.

1 Like