Tinderbox and Hook - moving notes

I don’t think you can without compromise. If you can live without the doc opening in the right view/scope but at least with the right note selected, a simple solution is tto make you own URL stripping out the internal path part. IOW instead of:

tinderbox://MyTestDoc/Projects/Trial%20Y?view=outline+select=tbx:BkDgwh;

use

tinderbox://MyTestDoc/?view=outline+select=tbx:BkDgwh;

BYW, another possible point of failure. The note URL includes the document name. If you rename the TBX, the inbound links will fail. not everyone’s problem but another point of which to beware.

It’s still not unambiguous why Hook is failing. I suspect is ti the in-doc path part, but until the breakage is identified, trying to build a fix seems like wasted effort.

If you want to make a custom path-less NoteURL using $IDString:

$MyString = "tinderbox://"+document["name"].substr(0,-4)+"/?view=outline+select="+$IDString+";";

In my test doc (starter.tbx), I get output like:

tinderbox://starter/?view=outline+select=tbx:BkDgyR;

I assume this would be on the Tinderbox side and not on the Hook AppleScript side correct.

Would this be in a stamp/edict?

I am understanding, you are suggesting adding a Display Attribute that you would click in the $Prototype / Note

Until / If there is an AppleScript way?

Tom

Not really, I simply used some action code to show the basic context. If you need to make the string on the fly in AppleScript, your re-write the logic in AppleScript. The constituent parts of the whole are:

  • literal string. "tinderbox://
  • target Tinderbox TBX document name without the file extension.
  • literal string /?view=outline+select=
  • the value of attribute “IDString” for the desired note
  • (I think the trailing semicolon ’ Tinderbox appends is un-needed for URL use)

Thanks Mark

How do I get the Tbx document name in AppleScript?

How do I do this?
" * target Tinderbox TBX document name without the file extension."

I tried,

set docName to value of attribute document [“name”] of openNote. // failed

If I use…

set docName to value of attribute “name” of openNote

//I get the note’s name, not the document name.

Tom

Doubtless there are lots of ways, but this works for me (using Script Debugger v8.0.5 on macOS 12.6.3):

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

tell application "Tinderbox 9"
	set theName to the name of the front document
end tell

set TID to text item delimiters
if (theName contains ".") and (theName does not end with ".") then
	set text item delimiters to {"."}
	set nameWithoutExtension to text 1 thru text item -2 of theName
else
	set nameWithoutExtension to theName
end if
set text item delimiters to TID

nameWithoutExtension -- this is your filename without the extension.

The easy bit is getting the document name. I’m then reminded AppleScript doesn’t have string functions (replace, substring, etc.), you have to write them yourself.

Anyway, the above is basic script. For real use, I’d turn that into a subroutine akin to making a function in Tinderbox action code (write it once, re-use the code many times.)

Here is the above with the filename extension removal placed into a subroutine:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

tell application "Tinderbox 9"
	set theName to the name of the front document
end tell

set documentName to getFilenameWithoutExtension(theName)

-- subroutine starts here
on getFilenameWithoutExtension(theFilename)
	set TID to text item delimiters
	if (theFilename contains ".") and (theFilename does not end with ".") then
		set text item delimiters to {"."}
		set filenameWithoutExtension to text 1 thru text item -2 of theFilename
	else
		set filenameWithoutExtension to theFilename
	end if
	set text item delimiters to TID
	
	return filenameWithoutExtension
	
end getFilenameWithoutExtension
1 Like

BTW, I’ve added AppleScript to the supported highlighting methods for the forum. When posting AppleScript code enclose the snipped with a line of 3 back-ticks before and after. On the opening line of back ticks ad a space and the word applescript and the forum sofware will use AppleScript syntax for highlighting.

There isn’t a Tinderbox action code language module for highlight.js (the library the Discourse forum software uses for the code highlighting) but someone with the coding smarts might be able to make one. the documentation for that is here: Supported Languages — highlight.js 11.7.0 documentation.

If using the 3-back-tick method to make a code example and you don’t want any colouring/styling, as " text" the tend of the opening line of back-ticks.

2 Likes

whew…

Hello HookMarkers and Tinderboxers!

After several days of testing… this version now seems to work (on my system). It seems to correct the moving notes losing the HookMark issue. This needs more testing. Let’s test it.

Warning … code below is my FIRST AS edited script. Actually not, there were many revisions prior to this one, I have been working on this one for 4 days. But it is my first time I have shared an AS script.

The code below should replace the Tinderbox 9 Hookmark Script that has not been updated since Tinderbox 8

In HookMark, go to Preferences/Scripts/Tinderbox 9/Get Address

-- original script by Rob Trew
-- edited by Tom Diaz
-- hints by Mark Anderson and Mark Bernstein

use framework "Foundation"

tell application "Tinderbox 9"
    if (count of documents) is equal to 0 then
        return "No document is available"
    end if
    
    set openFile to file of first document
    if openFile is missing value then
        return "Hookmark can't link unsaved files"
    end if
    
    set filePath to my encodedPath(POSIX path of (openFile as alias)) as string
    
    set openNote to selected note of first document
    if openNote is missing value then
        -- link to file if no note is selected
        return "file://" & filePath
    end if
    
    --original script commented out
    --set tinderboxURL to value of attribute "NoteURL" of openNote
    --set tinderboxURL to (text (1 + (length of "tinderbox://")) thru -1 of tinderboxURL)
    --set tinderboxURL to "tbx://" & tinderboxURL
    -- edited by Tom Diaz 20230314
    set docName to name of first document
    set docName to text 1 thru -5 of docName
    set tinderboxURL to value of attribute "ID" of openNote
    set tinderboxURL to "tinderbox://" & docName & "/?view=outline+select=" & tinderboxURL
    -- end of edit
    
    return tinderboxURL & "?filepath=" & filePath
end tell

-- encodedPath :: FilePath -> Percent Encoded String
on encodedPath(fp)
    tell current application
        (its ((NSString's stringWithString:fp)'s ¬
            stringByAddingPercentEncodingWithAllowedCharacters:(its NSCharacterSet's ¬
                URLPathAllowedCharacterSet))) as string
    end tell
end encodedPath

Test this first in a clean test doc. I will post this in HookMark, once we have more testing.

Let me know your feedback and see if this fixes the issue of losing HookMarks while moving notes.

Tom

3 Likes

This looks awesome, great stuff @TomD!!

1 Like

Hello,
Thanks, this works well! One small point that may help others, the comment syntax in what you posted made the " --" into one long dash and initially caused an error. I just deleted the comments and the script now works fine.

Yours,
Maurice

1 Like

@mpom Using my admin’s ‘hat’, I’ve fixed the mangled comments markers in @TomD’s code so all should now work when copy/pasted.

@TomD in Hookmark I see 4 script options in the Hookmark scripts for scripts for Tinderbox. I assume, based on existing content there, that people use the above script to replace the Get Address script:

1 Like
use framework "Foundation"

tell application "Tinderbox 9"
	if (count of documents) is equal to 0 then
		return "No document is available"
	end if
	
	set openFile to file of first document
	if openFile is missing value then
		return "Hookmark can't link unsaved files"
	end if
	
	set filePath to my encodedPath(POSIX path of (openFile as alias)) as string
	
	set openNote to selected note of first document
	if openNote is missing value then
		-- link to file if no note is selected
		return "file://" & filePath
	end if
	
	set docName to name of first document
	set docName to text 1 thru -5 of docName
	set tinderboxURL to value of attribute "IDString" of openNote
	set tinderboxURL to "tinderbox://" & docName & "/?view=outline+select=" & tinderboxURL
	
	return tinderboxURL
end tell

-- encodedPath :: FilePath -> Percent Encoded String
on encodedPath(fp)
	tell current application
		(its ((NSString's stringWithString:fp)'s ¬
			stringByAddingPercentEncodingWithAllowedCharacters:(its NSCharacterSet's ¬
				URLPathAllowedCharacterSet))) as string
	end tell
end encodedPath

OK. Several observations here:

  • this fails with a multiple selection (or rather it only records the first item in the selection (in order of selection, not $OutlineOrder order).
  • as noted $IDString isn’t currently (as at v9.5.2) URL-safe die to presence of forward -slash / and plus-sign + characters in the ID string. Given that use of $IDString was only suggested as a fix to a mis-diagnosed error, the change is not needed. Removing the (view container) path element from the URL, which you already do, is the real fix to the ID problem. So, no need for $IDString.

So, here is a revised script (I’ve left out comments for attribution, etc., for brevity/clarity whilst we’re still trying to fix this:

tell application "Tinderbox 9"

	if (count of documents) is equal to 0 then
		return "No document is available for linking"
	end if
	
	set openFile to file of first document
	if openFile is missing value then
		return "Hookmark can't link to unsaved files"
	end if
	
	set openNote to selected note of first document
	if openNote is missing value then
		return "No selection: Hookmark needs to link to selected note(s)"
	else
		set docName to name of first document
		set docName to text 1 thru -5 of docName
		set theSelectionList to selection of first document
		set theSelection to ""
		repeat with anItem in theSelectionList
			set x to count of items in theSelectionList
			set theID to value of attribute "ID" of anItem as text
			set theSelection to theSelection & theID & ";"
		end repeat
		set tinderboxURL to value of attribute "NoteURL" of openNote
		set hookURL to "tinderbox://" & docName & "/?view=outline+select=" & theSelection
	end if
	
	return hookURL
	
end tell

The above is not criticism of @TomD’s scripts—my AppleScript smarts are 20 years out of date!—but I’m simply peeling off cruft accumulated by innocent mis-diagnosis of the task at hand. My script retains the three error-diagnostic tests:

  1. Tinderbox is open but not document is open. This is unusual as calling /opening Tinderbox results in a new unsaved TBX being open, which is caught by…
  2. The front (current) document is an unsaved document. Even so, Hookmark needs a link to a note/notes which leads to…
  3. Testing one or more notes are selected.

The script merely returns error messages. It is assumed Hookmark is able to intercept and handle these errors. I couldn’t find any relevant Hookmark docs (which doesn’t imply they don’t exist!) clarifying this aspect of the scripting.

All tests OK, we recreate the AppleScript list of the selected Tinderbox objects as a string of IDs (this took me longer to figure than the explanation might suggest) and build the URL Hookmark needs.

To be clear, we’re in that stage where users have discovered a need/use for which the existing Tinderbox pseudo-protocol wasn’t (back in v6.x) intended. Thus it’s easy to misread the issue of poor AppleScript scripting or other user error. For now, I think the above works but, do please test as I’m busy on other things ATM and testing is very time-consuming and better done by those with a pressing need rather than a conceptual need. Regardless, experience thus far suggests that for the new needs at hand some review/revision of the tinderbox:// pseudo-protocol is necessary. But that needs both some discussion by experienced used and possible changes to the app, so isn’t here now (as at v9.5.2).

HTH, but do ask if not clear,

2 Likes

Works like a charm, with one exception, that is when the linked note is hidden by a folded parent note.

CleanShot 2023-03-16 at 15.20.59

I’m afraid the video is too small (scale/visual area) to understand what you mean.

Don’t forget that the current behaviour (script) above is that the right not is selected but it may not appear visibly in the view pane. IOW, it is a task for the user to reset the view as needed. It’s not a bug,. It’s a mismatch of magical thinking (I imagine X happening) with what the app can do currently. I keep saying it, if you want richer behaviour, make a feature request: rexplain what you want and the context of the need.

Hookmark is leveraging a pseudo-protocol devised for Tinderbox v.6 and it has some unstated assumptions:

  • target objects don’t move from their current path.
  • paths used in NoteURL don’t change.
  • the process can’t know about views added since it was created.

Within those parameters, I think Hook works as described. However, I also think those old v6-era assumptions are—unintentionally—not pertinent to today’s Tinderbox use. But fixing the later involves changes to the app that can’t be fixed with a Hook script change.

Yes, this is a known behavior of TBX, one that I’d really like to see changed. If you click to a note that is collapsed you can view it, but the outline will not expand. I’d love to see the outline expand the path of the specific note and take you there, or at least to have the option for this.

Does not seem to work for me, maybe someone can help me on Sat.

This has been a thoughtful and productive discussion, particularly for those who wish to use Hook with bi-directional links where one can start with an external (to Tinderbox) source and link to the specific Tinderbox note that it’s associated with. And as we see, the solution thus far is close, though not quite perfect when Tinderbox notes are moved.

Meanwhile, I’m sharing how I use Hook in a different, simpler way. I don’t start from an external source and link back to a Tinderbox note. Rather, I start with a Tinderbox note attribute and link it to an external file. I never lose track of Hook linked files. Hook links are very robust in this way, regardless of where I move Tinderbox notes.

Specifically, when I wish to link an external file to a Tinderbox note, I copy the external file link using the Hook app, and then I paste that Hook link into a Tinderbox URL type note attribute. At this point I’ve created a unidirectional link from the Tinderbox note attribute to the external file. Now, wherever I move the Tinderbox note, the attribute link is preserved. Likewise, wherever I move a linked file, Hook keeps track and takes me to the linked file. By starting in Tinderbox, I can always find the Hooked file and that’s good enough for my simpler usage needs.

I can still create bi-directional links, but what I’m doing does nothing to fix the problem addressed in this thread. It’s simply an alternative way to use Hook with Tinderbox in a productive way.

FWTW

3 Likes

By way of set-up for that:

  • what is the path you have stored? (i.e. the actual string as stored in Hookmark)
  • what did you expect?
  • and what do you see?