Hi there! I was playing around and wrote a little AppleScript that will populate a Bike outline with backlinks (and if you run it again, it will update/replace all the backlinks). Here is the code:
tell front document of application "Bike"
repeat with currentRow in rows
set currentId to id of currentRow
set currentUrl to URL of currentRow
set backlinks to {}
repeat with theRow in rows
tell theRow
set shouldScanTheRow to not (exists (attribute named "meta"))
end tell
if shouldScanTheRow then
repeat with theRun in attribute runs of text content of theRow
set theRunUrl to link of theRun
if link of theRun = currentUrl then
set backlinks to backlinks & (id of theRow)
end if
end repeat
end if
end repeat
tell currentRow
if exists row named "Backlinks" then
delete row named "Backlinks"
end if
end tell
if not (backlinks = {}) then
tell currentRow
set backlinksRow to make row with properties {name:"Backlinks"}
tell backlinksRow
set bold of text content to true
end tell
end tell
repeat with theBacklink in backlinks
set referrerRow to row id theBacklink
tell backlinksRow
set linkRow to make row with properties {name:name of referrerRow}
tell linkRow
make attribute with properties {name:"meta"}
set link of text content to URL of referrerRow
end tell
end tell
end repeat
end if
end repeat
end tell
Here is what a given outline looks like before running the script:
After I run the script, it looks like this:
(The code is really bad because I don’t know how to use applescript. I would like to have a more efficient one where I store the backlinks in a dictionary, but I don’t know how to do that.)
2 Likes
Sorry for messaging again, but I forgot to say: if Bike had some kind of a “palette” for easily selecting a node to link to (I am thinking of something like typing Cmd-Shift-O
and then getting a little search box that lets me filter through to choose a row, and then it spits out a link), I would be able to use Bike very easily for some very non-trivial personal organization tasks, in combination with the script that I wrote. For instance, this can be used to handle tagging. Of course, a more builtin approach to tagging and other things (maybe inspired by TaskPaper) would also be very welcome.
Anyway, thanks so much for the care you have put into the Bike outliner. It’s really a joy, and I’m excited to see it grow — which will make it possible for me to use it in more parts of my workflow.
1 Like
Here is a much faster version of the script:
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
property NSMutableDictionary : a reference to current application's NSMutableDictionary
property NSMutableArray : a reference to current application's NSMutableArray
set backlinksDict to NSMutableDictionary's dictionary()
tell front document of application "Bike"
-- initialize the backlinks dictionary
repeat with currentRow in rows
set currentUrl to URL of currentRow
set arr to NSMutableArray's array()
(backlinksDict's setValue:arr forKey:currentUrl)
end repeat
set rowsToDelete to {}
repeat with currentRow in rows
set currentId to id of currentRow
set currentUrl to URL of currentRow
tell currentRow
set rowIsMeta to exists (attribute named "meta")
end tell
if rowIsMeta then
set rowsToDelete to rowsToDelete & {currentId}
else
repeat with theRun in attribute runs of text content of currentRow
set theRunUrl to link of theRun
if exists theRunUrl then
set backlinks to (backlinksDict's valueForKey:theRunUrl)
if backlinks is not missing value then
(backlinks's addObject:currentUrl)
end if
end if
end repeat
end if
end repeat
repeat with theRowId in rowsToDelete
if exists (row id theRowId) then
delete row id theRowId
end if
end repeat
end tell
set allKeys to backlinksDict's allKeys()
repeat with theKey in allKeys
set links to (backlinksDict's valueForKey:theKey)
set currentRowId to (theKey's componentsSeparatedByString:"#")'s lastObject() as text
if not ((count of links) is 0) then
tell front document of application "Bike"
set currentRow to row id currentRowId
tell currentRow
set headerRow to make row with properties {name:"Backlinks"}
tell headerRow
set bold of text content to true
make attribute with properties {name:"meta"}
end tell
end tell
end tell
end if
repeat with theLink in links
set referrerId to (theLink's componentsSeparatedByString:"#")'s lastObject() as text
tell front document of application "Bike"
set referrerRow to row id referrerId
tell headerRow
set linkRow to make row with properties {name:name of referrerRow}
tell linkRow
make attribute with properties {name:"meta"}
set link of text content to URL of referrerRow
end tell
end tell
end tell
end repeat
end repeat
2 Likes
This is great to see, thanks for sharing it!
I’ve moved this script into it’s own topic so that it will be easier to find and link to in the future.
if Bike had some kind of a “palette” for easily selecting a node to link to
I agree this is a feature that Bike needs. Or more generally a pallet for finding rows and it could be used for a lot of things such as copy links, navigation, etc. Definitely on my list.
3 Likes