I frequently find myself copying links to specific pages of documents to include them in my notes. This way I can easily access the relevant passages on later review.
Though, I prefer to annotate with PDF Expert. This often entails finding the pdf in dt3, going to the corresponding page and copying the item link in order to get the referencing URL. I’d like to evade those steps.
-- Get the x-devonthink-item URL for the active document's page in PDF Expert
--
-- Via "Open DEVONthink record for current PDF Expert tab"
-- https://discourse.devontechnologies.com/t/script-open-devonthink-record-for-pdf-expert-tab/47243
-- solution for umlauts ("iconv -t UTF8-MAC") found here: https://stackoverflow.com/questions/23219482/bash-ps-grep-for-process-with-umlaut-os-x/23226449#23226449
tell application "System Events"
activate application "PDF Expert"
delay 1
tell process "PDF Expert"
click menu item "Gehe zu Seite..." of menu 1 of menu bar item "Gehe zu" of menu bar 1
end tell
tell application "System Events" to keystroke "c" using {command down}
delay 1
set pageNum to the clipboard
tell application "System Events"
key code 53
-- esc
end tell
delay 1
try
tell application process "PDF Expert"
tell window 1
set theFileName to value of attribute "AXTitle" & ".pdf"
if theFileName starts with "* " then set theFileName to characters 3 thru -1 in theFileName as string
end tell
set PID to unix id
end tell
on error error_message number error_number
if the error_number is not -128 then
display alert "System Events" & space & error_number message error_message as warning
return
end if
end try
end tell
set theOpenFiles to (do shell script "lsof -p " & PID)
set convertedOutput to (do shell script "iconv -t UTF8-MAC <<<$" & quoted form of theOpenFiles)
set theLines to paragraphs of convertedOutput
repeat with thisLine in theLines
if thisLine contains theFileName then
set thePath to characters (offset of "/" in thisLine) thru -1 in thisLine as string
exit repeat
end if
end repeat
tell application id "DNtp"
try
set theDatabases to databases
set theResults to {}
repeat with thisDatabase in theDatabases
set thisDatabasesResults to lookup records with path thePath in thisDatabase
set theResults to theResults & thisDatabasesResults
end repeat
if theResults = {} then
display notification "Dokumentpfad nicht in geöffneten Datenbanken enthalten!" with title "Lookup DEVONthink"
return
else
set theUUID to uuid of (item 1 of theResults)
set callback to "x-devonthink-item://" & theUUID & "?page=" & pageNum
set the clipboard to callback
display notification callback with title ("x-devonthink-item URL")
end if
on error error_message number error_number
if the error_number is not -128 then
display alert "DEVONthink Pro" & space & error_number message error_message as warning
return
end if
end try
end tell
I like the idea, but when you get the page with this method via PDF Expert, sometimes you’ll get the printed page number, but not the actual page DT3 needs for the link.
Just now I tested it on a PDF. The printed page number (and the number displayed by PDF Expert and DT3) was 47. But when I use the copy page URL command in DT3, the page number was 57. This because the pdf is not computing the pages numbered i to x.
This here will work with Adobe Acrobat and with Skim.
set thePage to ""
set thePath to ""
set front_app to (path to frontmost application as Unicode text)
if front_app contains "Acrobat" then
tell application "Adobe Acrobat"
-- activate
set theDoc to item 1 of PDF Windows
set thePage to get page number of theDoc
set thePage to thePage - 1
set thePath to file alias of front document
set thePath to POSIX path of thePath
end tell
end if
if front_app contains "Skim" then
tell application "Skim"
-- activate
set theDoc to front document
set thePage to get index for current page of theDoc
set thePage to thePage - 1
set thePath to the path of theDoc
end tell
end if
if thePage is not "" then
tell application id "DNtp"
try
set theDatabases to databases
set theResults to {}
repeat with thisDatabase in theDatabases
set thisDatabasesResults to lookup records with path thePath in thisDatabase
set theResults to theResults & thisDatabasesResults
end repeat
if theResults = {} then
display notification "Document could not be found in open databases" with title "Lookup DEVONthink"
return
else
set theUUID to uuid of (item 1 of theResults)
set callback to "x-devonthink-item://" & theUUID & "?page=" & thePage
set the clipboard to callback
display notification callback with title ("x-devonthink-item URL")
end if
on error error_message number error_number
if the error_number is not -128 then
display alert "DEVONthink Pro" & space & error_number message error_message as warning
return
end if
end try
end tell
end if
thanks for pointing that out! While for most cases that won’t cause a problem for me, it would be nice to have a workaround. Just in case.
I observed something: Assume you have a document with pages i-v followed by pages 1-10: A pair of two ranges <i-v,1-10>, say the curated page count, at 15 pages total, say the actual page count.
If I run the script on the document viewed in PDF Expert on page 6 (of the curated page count), the reference URL will bring me to page 1 (curated) in dt3 or page 6 (actual) respectively, just as you pointed out (the desired position in the actual page count’s range is 11). Now the observation: If I click on the current page/ page count indicator[^1] in dt3 and enter ‘6’, it brings me to the correct (curated) page. Dt3 handles the alphanumerical mix just fine. If I’m in the range <i-v> the indicator also displays, e.g. “iv”.
So, the record must have the relevant information as one of its properties, right? If we had access to it, then there was a workaround. What we can access however, as far as I can tell, is just this:
page count (integer, r/o) : The page count of a record. Currently only supported by PDF documents.
With information about both sides of the pair we could simply add the left range to the current page position (if >= 1) and had the correct reference URL. Could this be done, developers?
-- Get the x-devonthink-item URL for the active document's page in PDF Expert v.2
--
-- Via "Open DEVONthink record for current PDF Expert tab"
-- https://discourse.devontechnologies.com/t/script-open-devonthink-record-for-pdf-expert-tab/47243
-- solution for umlauts ("iconv -t UTF8-MAC") found here: https://stackoverflow.com/questions/23219482/bash-ps-grep-for-process-with-umlaut-os-x/23226449#23226449
tell application "System Events"
activate application "PDF Expert"
delay 1
tell process "PDF Expert"
click menu item "Gehe zu Seite..." of menu 1 of menu bar item "Gehe zu" of menu bar 1
end tell
tell application "System Events" to keystroke "c" using {command down}
delay 1
set pageNum to the clipboard
tell application "System Events"
key code 53
-- esc
end tell
delay 1
tell process "PDF Expert"
click menu item "Letzte Seite" of menu 1 of menu bar item "Gehe zu" of menu bar 1
delay 1
click menu item "Gehe zu Seite..." of menu 1 of menu bar item "Gehe zu" of menu bar 1
end tell
tell application "System Events" to keystroke "c" using {command down}
delay 1
set lastPageCurated to the clipboard
set the clipboard to pageNum
tell application "System Events" to keystroke "v" using {command down}
tell application "System Events"
key code 36
-- esc
end tell
delay 1
try
tell application process "PDF Expert"
tell window 1
set theFileName to value of attribute "AXTitle" & ".pdf"
if theFileName starts with "* " then set theFileName to characters 3 thru -1 in theFileName as string
end tell
set PID to unix id
end tell
on error error_message number error_number
if the error_number is not -128 then
display alert "System Events" & space & error_number message error_message as warning
return
end if
end try
end tell
set theOpenFiles to (do shell script "lsof -p " & PID)
set convertedOutput to (do shell script "iconv -t UTF8-MAC <<<$" & quoted form of theOpenFiles)
set theLines to paragraphs of convertedOutput
repeat with thisLine in theLines
if thisLine contains theFileName then
set thePath to characters (offset of "/" in thisLine) thru -1 in thisLine as string
exit repeat
end if
end repeat
tell application id "DNtp"
try
set theDatabases to databases
set theResults to {}
repeat with thisDatabase in theDatabases
set thisDatabasesResults to lookup records with path thePath in thisDatabase
set theResults to theResults & thisDatabasesResults
end repeat
if theResults = {} then
display notification "Dokumentpfad nicht in geöffneten Datenbanken enthalten!" with title "Lookup DEVONthink"
return
else
set theUUID to uuid of (item 1 of theResults)
set totalPageCount to page count of (item 1 of theResults)
if lastPageCurated is not equal to totalPageCount then
set alphaNum to (totalPageCount - lastPageCurated)
set pageNum to (pageNum + alphaNum)
end if
set callback to "x-devonthink-item://" & theUUID & "?page=" & (pageNum - 1)
set the clipboard to callback
display notification callback with title ("URL copied to clipboard:")
end if
on error error_message number error_number
if the error_number is not -128 then
display alert "DEVONthink Pro" & space & error_number message error_message as warning
return
end if
end try
end tell
Btw. the x-devonthink-item URL is zero-based on purpose, right (and will always stay that way)?
-- Get the x-devonthink-item:// URL for the active document's page viewed in PDF Expert
-- Credit: https://discourse.devontechnologies.com/t/script-open-devonthink-record-for-pdf-expert-tab/47243
-- Solution for umlauts ("iconv -t UTF8-MAC"): https://stackoverflow.com/a/23226449/7625403
tell application "System Events"
activate application "PDF Expert"
delay 0.5
tell process "PDF Expert" to keystroke "g" using {command down, option down} -- open go to page modal
tell application "System Events" to keystroke "c" using command down
delay 0.5
set pageNum to the clipboard
tell application "System Events" to key code 53 -- esc
tell application "System Events" to key code 125 using command down -- ⌘↓
tell process "PDF Expert" to keystroke "g" using {command down, option down} -- open go to page modal
tell application "System Events" to keystroke "c" using command down -- copy the page number
delay 0.5
set lastPageCurated to the clipboard
set the clipboard to pageNum
tell application "System Events" to keystroke "v" using command down -- go back to the original page
tell application "System Events" to key code 36 -- return / enter
delay 0.5
try
tell application process "PDF Expert"
tell window 1
set theFileName to value of attribute "AXTitle" & ".pdf"
if theFileName starts with "* " then set theFileName to characters 3 thru -1 in theFileName as string
end tell
set PID to unix id
end tell
on error error_message number error_number
if the error_number is not -128 then
display alert "System Events" & space & error_number message error_message as warning
return
end if
end try
end tell
set theOpenFiles to (do shell script "lsof -p " & PID)
set convertedOutput to (do shell script "iconv -t UTF8-MAC <<<$" & quoted form of theOpenFiles)
set theLines to paragraphs of convertedOutput
repeat with thisLine in theLines
if thisLine contains theFileName then
set thePath to characters (offset of "/" in thisLine) thru -1 in thisLine as string
exit repeat
end if
end repeat
tell application id "DNtp"
try
set theDatabases to databases
set theResults to {}
repeat with thisDatabase in theDatabases
set thisDatabasesResults to lookup records with path thePath in thisDatabase
set theResults to theResults & thisDatabasesResults
end repeat
if theResults = {} then
display notification "Document path not found in open databases!" with title "Lookup DEVONthink"
return
else
set theUUID to uuid of (item 1 of theResults)
set totalPageCount to page count of (item 1 of theResults)
if lastPageCurated is not equal to totalPageCount then
set alphaNum to (totalPageCount - lastPageCurated)
set pageNum to (pageNum + alphaNum)
end if
set callback to "x-devonthink-item://" & theUUID & "?page=" & (pageNum - 1)
set the clipboard to callback
end if
on error error_message number error_number
if the error_number is not -128 then
display alert "DEVONthink 3" & space & error_number message error_message as warning
return
end if
end try
end tell
Indeed, this is a known problem for which I have no workaround. Even if I convert the roman number to decimal, the end of the preface enumerated with roman numbers remains unknown (and the difference would have to be subtracted from the total page count).
Btw., the Alfred Workflow now has a proper home with additional info, including the known issues:
-- Copy the page number in PDF Expert
tell application "System Events"
tell process "PDF Expert" to keystroke "g" using {command down, option down} -- open go to page modal
tell application "System Events" to keystroke "c" using command down
delay 0.5
tell application "System Events" to key code 53 -- esc
end tell
-- Open DEVONthink record for current PDF Expert tab
-- Source: https://discourse.devontechnologies.com/t/script-open-devonthink-record-for-pdf-expert-tab/47243
tell application "System Events"
try
tell application process "PDF Expert"
tell window 1
set theFileName to value of attribute "AXTitle" & ".pdf"
if theFileName starts with "* " then set theFileName to characters 3 thru -1 in theFileName as string
end tell
set PID to unix id
end tell
on error error_message number error_number
if the error_number is not -128 then
display alert "System Events" & space & error_number message error_message as warning
return
end if
end try
end tell
set theOpenFiles to (do shell script "lsof -p " & PID)
set convertedOutput to (do shell script "iconv -t UTF8-MAC <<<$" & quoted form of theOpenFiles)
set theLines to paragraphs of convertedOutput
repeat with thisLine in theLines
if thisLine contains theFileName then
set thePath to characters (offset of "/" in thisLine) thru -1 in thisLine as string
exit repeat
end if
end repeat
tell application id "DNtp"
try
set theDatabases to databases
set theResults to {}
repeat with thisDatabase in theDatabases
set thisDatabasesResults to lookup records with path thePath in thisDatabase
set theResults to theResults & thisDatabasesResults
end repeat
if theResults = {} then
display notification "Pfad nicht in offenen Datenbanken enthalten!" with title "Lookup DEVONthink"
return
else
open window for record (item 1 of theResults)
activate
end if
on error error_message number error_number
if the error_number is not -128 then
display alert "DEVONthink Pro" & space & error_number message error_message as warning
return
end if
end try
end tell
The issue of this way is that the DEVONthink window would be open, but it doesn’t matter in most cases.
Turns out there is a solution to the problem after all Thanks @chrillek for the tip!
@TomBen, there is an updated version of the Alfred workflow on Github if you want to check it out.
And here is the updated script:
-- Part of the DEVONthink ↔ PDF Expert workflow for Alfred
-- https://github.com/zeitlings/alfred-workflows#14-devonthink--pdf-expert
--
-- Get the DEVONthink reference URL for the page viewed in PDF Expert
-- ===================================================================
-- Credits
-- - pete31: https://discourse.devontechnologies.com/t/script-open-devonthink-record-for-pdf-expert-tab/47243
-- - Umlaut fix: https://stackoverflow.com/a/23226449/7625403
use AppleScript version "2.4"
use framework "PDFKit"
use scripting additions
property NSURL : a reference to current application's NSURL
property NSString : a reference to current application's NSString
property PDFDocument : a reference to current application's PDFDocument
on run argv
tell application "System Events"
activate application "PDF Expert"
delay 0.5
tell process "PDF Expert" to keystroke "g" using {command down, option down} -- go to
tell application "System Events" to keystroke "c" using command down
delay 0.5
tell application "System Events" to key code 53 -- esc
set theActiveLabel to the clipboard
try
tell application process "PDF Expert"
tell window 1
set theFileName to value of attribute "AXTitle" & ".pdf"
if theFileName starts with "* " then set theFileName to characters 3 thru -1 in theFileName as string
end tell
set PID to unix id
end tell
on error error_message number error_number
return "Error with code " & (error_number as text) & " " & (error_message as text)
end try
end tell
set thePath to my recoveredPath(theFileName, PID)
set theURL to NSURL's fileURLWithPath:(NSString's stringWithString:thePath)
set pdf to PDFDocument's alloc()'s initWithURL:theURL
set theCount to pdf's pageCount()
set thePageIndex to -1
set cur to 0
repeat while cur < theCount
set thePage to pdf's pageAtIndex:cur
set theLabel to thePage's label()
if theLabel ≠ missing value then
if (theLabel as text) is theActiveLabel then
set thePageIndex to cur
exit repeat
end if
end if
set cur to cur + 1
end repeat
if thePageIndex is equal to -1 then
return "Unable to recover Page Index"
end if
set pageLink to my referenceURL(thePath, thePageIndex)
try
set the clipboard to pageLink
return pageLink
on error number -2753 -- not defined
return "Document not found in any open Database"
end try
end run
on recoveredPath(theFileName, PID)
set theOpenFiles to (do shell script "lsof -p " & PID)
set convertedOutput to (do shell script "iconv -t UTF8-MAC <<<$" & quoted form of theOpenFiles)
set theLines to paragraphs of convertedOutput
repeat with thisLine in theLines
if thisLine contains theFileName then
set thePath to characters (offset of "/" in thisLine) thru -1 in thisLine as string
return thePath
end if
end repeat
end recoveredPath
on referenceURL(thePath, thePageIndex)
tell application id "DNtp"
try
set theDatabases to databases
set theResults to {}
repeat with thisDatabase in theDatabases
set dbResults to lookup records with path thePath in thisDatabase
set theResults to theResults & dbResults
end repeat
if theResults = {} then
return
else
set theUUID to uuid of (item 1 of theResults)
set referenceURL to "x-devonthink-item://" & theUUID & "?page=" & (thePageIndex as text)
return referenceURL
end if
on error error_message number error_number
return "Error with code " & (error_number as text) & " " & (error_message as text)
end try
end tell
end referenceURL
DEVONthink 3.9 introduced deep links to select text and PDF annotations. So is it possible to copy DEVONthink’s annotation link in PDF Expert directly? Although it seems quite cumbersome.
(*
Part of the DEVONthink ↔ PDF Expert workflow for Alfred v2.1.0
https://github.com/zeitlings/alfred-workflows#14-devonthink--pdf-expert
Get the DEVONthink reference URL for the page viewed in PDF Expert
====================================================================
Credits
- pete31: https://discourse.devontechnologies.com/t/script-open-devonthink-record-for-pdf-expert-tab/47243
- Umlaut fix: https://stackoverflow.com/a/23226449/7625403
*)
use AppleScript version "2.4"
use framework "PDFKit"
use scripting additions
property NSURL : a reference to current application's NSURL
property NSString : a reference to current application's NSString
property PDFDocument : a reference to current application's PDFDocument
on run argv
tell application "System Events"
set bufferedClipboard to the clipboard
activate application "PDF Expert"
delay 0.5
tell process "PDF Expert" to keystroke "c" using {command down}
delay 0.2
set perhapsSelection to the clipboard as text
tell process "PDF Expert" to keystroke "g" using {command down, option down} -- go to
tell application "System Events" to keystroke "c" using command down
delay 0.5
tell application "System Events" to key code 53 -- esc
set theActiveLabel to the the clipboard
try
tell application process "PDF Expert"
tell window 1
set theFileName to value of attribute "AXTitle" & ".pdf"
if theFileName starts with "* " then set theFileName to characters 3 thru -1 in theFileName as string
end tell
set PID to unix id
end tell
on error error_message number error_number
return "Error with code " & (error_number as text) & " " & (error_message as text)
end try
end tell
set thePath to my recoveredPath(theFileName, PID)
set theURL to NSURL's fileURLWithPath:(NSString's stringWithString:thePath)
set pdf to PDFDocument's alloc()'s initWithURL:theURL
set theCount to pdf's pageCount()
set thePageIndex to -1
set cur to 0
repeat while cur < theCount
set thePage to pdf's pageAtIndex:cur
set theLabel to thePage's label()
if theLabel ≠ missing value then
if (theLabel as text) is theActiveLabel then
set thePageIndex to cur
exit repeat
end if
end if
set cur to cur + 1
end repeat
if thePageIndex is equal to -1 then
set the cliboard to bufferedClipboard
return "Unable to recover Page Index"
end if
set pageLink to my referenceURL(thePath, thePageIndex)
try
-- Build page selection
set thePage to pdf's pageAtIndex:thePageIndex
set theText to thePage's |string|()
set theRange to theText's rangeOfString:perhapsSelection
if theRange's |length|() ≠ 0 then
set theStart to theRange's location() as text
set theLength to theRange's |length|() as text
set theSelection to NSString's stringWithString:perhapsSelection
set theSearchString to theSelection's stringByAddingPercentEncodingWithAllowedCharacters:(current application's NSCharacterSet's URLQueryAllowedCharacterSet())
set pageSelectionLink to pageLink & "&start=" & theStart & "&length=" & theLength & "&search=" & theSearchString
set the clipboard to pageSelectionLink
return pageSelectionLink
end if
set the clipboard to pageLink
return pageLink
on error number -2753 -- not defined
return "Document not found in any open Database"
end try
end run
on recoveredPath(theFileName, PID)
set theOpenFiles to (do shell script "lsof -p " & PID)
set convertedOutput to (do shell script "iconv -t UTF8-MAC <<<$" & quoted form of theOpenFiles)
set theLines to paragraphs of convertedOutput
repeat with thisLine in theLines
if thisLine contains theFileName then
set thePath to characters (offset of "/" in thisLine) thru -1 in thisLine as string
return thePath
end if
end repeat
end recoveredPath
on referenceURL(thePath, thePageIndex)
tell application id "DNtp"
try
set theDatabases to databases
set theResults to {}
repeat with thisDatabase in theDatabases
set dbResults to lookup records with path thePath in thisDatabase
set theResults to theResults & dbResults
end repeat
if theResults = {} then
return
else
set theUUID to uuid of (item 1 of theResults)
set referenceURL to "x-devonthink-item://" & theUUID & "?page=" & (thePageIndex as text)
return referenceURL
end if
on error error_message number error_number
return "Error with code " & (error_number as text) & " " & (error_message as text)
end try
end tell
end referenceURL
To get the full annotation link, your text selection just needs to overlap it. I anticipate poor performance for very large PDFs and in cases where the selected text occurs quite often in the document. (Because of the pdf's findString:textSelection withOptions:3). For these cases, the annotation check can be disabled in the (alfred) configuration.
p.s. There really is no way to call CGRectIntersectsRect from AppleScript, or any other ObjC method for that matter, right?
(*
Part of the DEVONthink ↔ PDF Expert workflow for Alfred v2.1.1
https://github.com/zeitlings/alfred-workflows#14-devonthink--pdf-expert
Get the DEVONthink page link, selection link, or annotation link for the page viewed in PDF Expert
====================================================================
Credits
- pete31: https://discourse.devontechnologies.com/t/script-open-devonthink-record-for-pdf-expert-tab/47243
- Umlaut fix: https://stackoverflow.com/a/23226449/7625403
*)
use AppleScript version "2.4"
use framework "PDFKit"
use scripting additions
property NSURL : a reference to current application's NSURL
property NSString : a reference to current application's NSString
property PDFDocument : a reference to current application's PDFDocument
on run argv
set checkForAnnotations to (item 1 of argv as integer) as boolean
tell application "System Events"
set bufferedClipboard to the clipboard
activate application "PDF Expert"
delay 0.5
tell process "PDF Expert" to keystroke "c" using {command down}
delay 0.2
set perhapsSelection to the clipboard as text
tell process "PDF Expert" to keystroke "g" using {command down, option down} -- go to
tell application "System Events" to keystroke "c" using command down
delay 0.5
tell application "System Events" to key code 53 -- esc
set theActiveLabel to the clipboard
try
tell application process "PDF Expert"
tell window 1
set theFileName to value of attribute "AXTitle" & ".pdf"
if theFileName starts with "* " then set theFileName to characters 3 thru -1 in theFileName as string
end tell
set PID to unix id
end tell
on error error_message number error_number
return "Error with code " & (error_number as text) & " " & (error_message as text)
end try
end tell
set thePath to my recoveredPath(theFileName, PID)
set theURL to NSURL's fileURLWithPath:(NSString's stringWithString:thePath)
set pdf to PDFDocument's alloc()'s initWithURL:theURL
set theCount to pdf's pageCount()
set thePageIndex to -1
set cur to 0
repeat while cur < theCount
set thePage to pdf's pageAtIndex:cur
set theLabel to thePage's label()
if theLabel ≠ missing value then
if (theLabel as text) is theActiveLabel then
set thePageIndex to cur
exit repeat
end if
end if
set cur to cur + 1
end repeat
if thePageIndex is equal to -1 then
set the cliboard to bufferedClipboard
return "Unable to recover Page Index"
end if
set pageLink to my referenceURL(thePath, thePageIndex)
try
set thePage to pdf's pageAtIndex:thePageIndex
-- ------------------------------------- --
-- Check for annotation intersection --
-- ------------------------------------- --
if checkForAnnotations then
set theSelections to pdf's findString:perhapsSelection withOptions:3
repeat with thisSelection in theSelections
if (thisSelection's pages() as list) contains thePage then
set theBounds to (thisSelection's boundsForPage:thePage)
set theOrigin to item 1 of theBounds
set theSize to item 2 of theBounds
set coorX to item 1 of theOrigin
set coorY to item 2 of theOrigin
set width to item 1 of theSize
set height to item 2 of theSize
repeat with thisAnnotation in thePage's annotations()
set annotationBounds to thisAnnotation's |bounds|()
set annotationOrigin to item 1 of annotationBounds
set annotationSize to item 2 of annotationBounds
set annoX to item 1 of annotationOrigin
set annoY to item 2 of annotationOrigin
set annoWidth to item 1 of annotationSize
set annoHeight to item 2 of annotationSize
set a to (coorX < (annoX + annoWidth))
set b to ((coorX + width) > annoX)
set c to (coorY < (annoY + annoHeight))
set d to ((coorY + height) > annoY)
set isIntersecting to a and b and c and d
if isIntersecting then
set theType to thisAnnotation's type() as text -- possibly nil
if theType is missing value then
set theType to "Highlight"
end if
set x to (round annoX rounding as taught in school) as text -- ....
set y to (round annoY rounding as taught in school) as text
set deepAnnotationLink to (pageLink as text) & "&annotation=" & theType & "&x=" & x & "&y=" & y
set the clipboard to deepAnnotationLink
return deepAnnotationLink
end if
end repeat
end if
end repeat
end if
-- ------------------------------ --
-- Reconstruct page selection --
-- ------------------------------ --
set theText to thePage's |string|()
set theRange to theText's rangeOfString:perhapsSelection
if theRange's |length|() ≠ 0 then
set theStart to theRange's location() as text
set theLength to theRange's |length|() as text
set theSelection to NSString's stringWithString:perhapsSelection
set theSearchString to theSelection's stringByAddingPercentEncodingWithAllowedCharacters:(current application's NSCharacterSet's URLQueryAllowedCharacterSet())
set deepSelectionLink to pageLink & "&start=" & theStart & "&length=" & theLength & "&search=" & theSearchString
set the clipboard to deepSelectionLink
return deepSelectionLink
end if
set the clipboard to pageLink
return pageLink
on error number -2753 -- not defined
set the cliboard to bufferedClipboard
return "Document not found in any open Database"
end try
end run
on recoveredPath(theFileName, PID)
set theOpenFiles to (do shell script "lsof -p " & PID)
set convertedOutput to (do shell script "iconv -t UTF8-MAC <<<$" & quoted form of theOpenFiles)
set theLines to paragraphs of convertedOutput
repeat with thisLine in theLines
if thisLine contains theFileName then
set thePath to characters (offset of "/" in thisLine) thru -1 in thisLine as string
return thePath
end if
end repeat
end recoveredPath
on referenceURL(thePath, thePageIndex)
tell application id "DNtp"
try
set theDatabases to databases
set theResults to {}
repeat with thisDatabase in theDatabases
set dbResults to lookup records with path thePath in thisDatabase
set theResults to theResults & dbResults
end repeat
if theResults = {} then
return
else
set theUUID to uuid of (item 1 of theResults)
set referenceURL to "x-devonthink-item://" & theUUID & "?page=" & (thePageIndex as text)
return referenceURL
end if
on error error_message number error_number
return "Error with code " & (error_number as text) & " " & (error_message as text)
end try
end tell
end referenceURL
Why did it report error: Execute an AppleScript failed with script error: text-script:837:844: execution error: Can’t make item 1 of {} into type integer. (-1700) when executing the AppleScript in Keyboard Maestro? However, the Alfred workflow works as expected.
Keyboard Maestro uses a pristine vanilla shell, rather than importing the ENV of Terminal.app, which has custom search paths defined in it.
(Alfred, in contrast, chooses to use the Terminal.app environment)
For use in KM, you would need to expand iconv to the full path on your system, which might, for example, depending on macOS version, be something like:
/usr/bin/iconv
but in any case, you should check first, using the Terminal command line:
Thank you. I followed your instruction to specify the full path of iconv, but it still encountered errors:
2023-04-05 21:11:03 Execute macro “Copy DEVONthink Annotation Link in PDF Expert” from trigger The Hot Key ⌥⇧L is pressed
2023-04-05 21:11:03 Action 12390747 failed: Execute an AppleScript failed with script error: text-script:837:844: execution error: Can’t make item 1 of {} into type integer. (-1700)
2023-04-05 21:11:03 Execute an AppleScript failed with script error: text-script:837:844: execution error: Can’t make item 1 of {} into type integer. (-1700). Macro “Copy DEVONthink Annotation Link in PDF Expert” cancelled (while executing Execute AppleScript).