Scrivener 3 and Hook

Wow! I’m very grateful for your fantastic input, @RobTrew! (and I’m sure Bi Ling will be too!)

Something along these (trying applescript this time) might be a bit faster (more cacheing, less abstraction)

(Again, you will have more experience of timing and so forth than I do)

(Make sure you scroll to copy the whole script – which ends with end tell)

-- Rob Trew 2020
-- Ver 0.02

tell application "Scrivener" to activate
tell application "System Events"
    set ps to processes where its name is "Scrivener"
    if {} ≠ ps then
        set menuBar to menu bar 1 of (item 1 of ps)
        
        -- FOCUS TO BINDER
        set focusBinder to menu item "Binder" of menu 1 of ¬
            (menu item "Move Focus To" of (menu "Navigate" of menuBar))
        if enabled of focusBinder then
            click focusBinder
        else
            -- The Show Binder / Hide Binder label state is not always quite as expected.
            click (first menu item of (menu "View" of menuBar) ¬
                where name ends with "Binder")
            delay 0.1
            click focusBinder
            delay 0.1
        end if
        
        -- NAME COPIED
        set menuEdit to (menu "Edit" of menuBar)
        click (menu item "Copy" of menuEdit)
        delay 0.2
        set strName to the clipboard
        
        -- URL COPIED
        click (menu item "Copy Document as External Link" of menu ¬
            of (menu item "Copy Special" of menuEdit))
        delay 0.2
        set mdLink to "[" & strName & "](" & (the clipboard) & ")"
        -- set the clipboard to mdLink
        return mdLink
    else
        ""
    end if
end tell
1 Like

Meanwhile AmberV at the Literature and Latte forum helpfully suggests an alternative GUI scripting route:

https://www.literatureandlatte.com/forum/viewtopic.php?p=308444#p308444

I’ll take a look and perhaps update that script tonight, unless anyone feels inclined to beat me to it.

1 Like

In the meanwhile I’ve posted a Keyboard Maestro macro taking the route suggested by AmberV on the Literature and Latte forum:

https://www.literatureandlatte.com/forum/viewtopic.php?p=308451#p308451

An advantage of such macros is that we can assign a single keystroke to them.

I find the ergonomic and cognitive processing costs imposed by Hook unusually high, and a bit discouraging, so in practice I’ve put it aside, though its does still potentially interest me. In particular Hook imposes:

  • Multiple keypresses to get the Hook dialog to display,
  • a wait until that dialog appears,
  • and then still a further keypress (⌘M) to copy a Markdown link.

This is all cognitively pretty noisy and resource-consuming, by any standards.

These additional processing costs might become better value if the Hook database became visible enough to be more enabling than frustrating, but in the meanwhile, Markdown links for my TaskPaper files are all I need, and it’s easier to assign a single key in Keyboard Maestro, which can interpret the meaning of that keystroke in the context of the foreground application.

(The KM route also facilitates visual notification of what has been copied, and seems to run a little more snappily too).

Hook may become more useful if:

  • we get a visible and clickable network graph of the database,
  • and the ratio of cognitive effort to value created generally catches up with Apple UI norms.

Hey @RobTrew, thanks for your work on this, here’s the script we ended up including in Hook, a modified version of what you’ve done

set the clipboard to ""
tell application "System Events"
	tell process "Scrivener"
		tell menu bar 1
			
			-- check if binder is hidden
			click menu item 3 of menu 1 of menu item "Move Focus To" of menu "Navigate"
			set isHidden to not enabled of menu item "Copy Document as External Link" of menu 1 of menu item "Copy Special" of menu "Edit"
			
			-- show binder, select item in binder, move focus to binder
			click menu item "Reveal in Binder" of menu "Navigate"
			click menu item 3 of menu 1 of menu item "Move Focus To" of menu "Navigate"
			
			-- get address
			click menu item "Copy Document as External Link" of menu 1 of menu item "Copy Special" of menu "Edit"
			delay 0.1
			set scrivAddr to the clipboard
			
			-- get name
			click menu item "Copy" of menu "Edit"
			delay 0.1
			set scrivName to the clipboard
			
			-- hide binder
			if isHidden then
				click menu item 5 of menu "View"
			end if
			
			return "[" & scrivName & "](" & scrivAddr & ")"
		end tell
	end tell
end tell

some notes:

We don’t check that the process exists. If it doesn’t exist then the script will throw an error which Hook will catch and log.

We set the clipboard to “” because if the “Copy” commands fail, the script will return a markdown link with whatever is in the clipboard, and if a URL is in the clipboard, Hook will believe that a valid link was returned, if []() is returned Hook will discard it as garbage.

As you noticed, the “Hide/Show Binder” menu item label changes. The “Move Focus To>Binder” also changes, so for both of those we access the menu items by index number.

Navigate>Reveal in Binder is better for showing the binder than “Show Binder” because

  1. It works whether or not binder is hidden, no need to check
  2. It selects the current item in the binder

#1 is actually a moot point because we check whether the binder is hidden so that we can re-hide it again later

But #2 handles an edge case in which two documents are open, in top and bottom editor, and the binder selection and the focused editor don’t match. Reveal in Binder will move the selection to the correct item.

As mentioned above, we track whether the binder was hidden at the start, and re-hide it at finish.

After clicking “Move Focus To>Binder”, “Edit>Copy” doesn’t work until the UI updates with the new focus and selected item, which requires a delay. But “Copy Document as External Link” works immediately. So by getting the address before the name, we’re able to remove a delay because the delay for the clipboard after copying the address serves dual purpose as delay for the UI to update for “Edit>Copy”

Delays in UI scripting are more of an art than a science but, knock on wood, 0.1 is enough for the clipboard

Code golf is a game, not a useful exercise, but if we didn’t care about re-hiding the binder, which isn’t strictly necessary, we could reduce the script to just this:

set the clipboard to ""
tell application "System Events" to tell process "Scrivener"
	-- show binder, select item in binder, move focus to binder
	click menu item "Reveal in Binder" of menu "Navigate" of menu bar 1
	click menu item 3 of menu 1 of menu item "Move Focus To" of menu "Navigate" of menu bar 1
	-- get address
	click menu item "Copy Document as External Link" of menu 1 of menu item "Copy Special" of menu "Edit" of menu bar 1
	delay 0.1
	set scrivAddr to the clipboard
	-- get name
	click menu item "Copy" of menu "Edit" of menu bar 1
	delay 0.1
	return "[" & (the clipboard) & "](" & scrivAddr & ")"
end tell

V 103 release notes: Hook integration scripts v. 103: Updated Scrivener support

Many thanks to everyone who contributed to putting this together so quickly. Much appreciated.

1 Like

I’m a small business owner (no programing skills). I recently tried hook with with our writing app (Scrivener). Am I missing something? I’m unable to make a direct link to a specific Scrivener document within a Scrivener project. Do I have that right?

I see something about scripts loading. Unfortunately, I’m seemingly unable to grab to connect to a specific scrivener doc.

What am I missing?

Currently the scripts out of the box just link to the entire document. No deep linking.

Deep linking is on our radar as something to do generally across the board (e.g., PDFs too.) At that point we’ll update the https://hookproductivity.com/help/integration/ page. Third party devs may wish to get in touch. Till then, there are ways to tailor specific scripts for that. Depends partly on what the linkable app API.

You can use Hook to get links to all kinds of things which you can paste into research documents that are part of Scrivener books (or whatever they are currently called in Scrivener.)

Hi Luc, thanks for the quick reply. I look forward the Deep Linking capability.

Hi again, @kadso. Are you using Scrivener 3?

I’ve been interacting with the helpful Literature & Latte in a support thread with one of our mutual customers. Literature & Latte indicate that Hook-Scrivener integration scripts work fine for them.

I’ve had a look at this myself with Scrivener 3, and I have also found that Hook’s current integration scripts work fine. This has inspired me to use Scrivener again for some of my writing projects. (I have an eternally nearly complete book: Discontinuities: Love, Art, Mind, and my research on perturbance will one day lead to a book on “emotions”.)

There’s a natural fit between Scrivener and Hook, given that Hook can enable users to paste research links, and link to research documents.

If you encounter issues please let us know.

Thanks Luc. This is good news. What I’m think I’m hearing is with the scripts available in Hook, I can link directly to specific scrivener documents within a particular project? If there is more, I missed it. Please advise…

It has been my experience that this works as you describe: Hook allows linking to and from specific documents within a Scrivener project.

1 Like

that’s right.
If the setting is English. UI scripts need localized versions. We intend to internationalize the Scrivener integration.

thanks for the quick reply(s). I’ve blocked time out for this item, this week. I’ll keep you in the loop.

1 Like

Luc, any examples or videos on EXACTLY how you’ve used Scrivener with Hook? I was thrilled to find that there is an integration. I am using it, but just out of curiosity, wanted to know if I’m missing something.

Hi Luc,

OK, some hand holding is needed on my part.

∞1 I’ve read through the above.

∞2 I see the code in Hook app > preference > Scrivener > Get Address (thanks Rob Trew)

∞3 But when I’m in Scrivener with a scrivener document selected and invoke the hook app the resulting window displays the “No Linkable items in Scrivener” window.

What am I missing and how do I use hook to link a scrivener doc to other items?

Thank you! we’ll internationalize Scrivener.

We had hoped to be further along internationalization by now (the entire app). It is a priority for 2.3 / 2.4.