How to export the results list for the "See also & Classify" command

I’m pretty sure your question how to get the names from the inspector and initially not mentioning that you’re dealing with a larger number of records led everybody in this thread in the wrong direction.

Luckily you’ve mentioned it now and luckily @cgrunenberg explained to me the differences between some AppleScript commands and what I saw in the See Also inspector today.

Maybe I’m missing something obvious, which is well possible, but I think I’ve found the way I would go if I wanted to share See Also results. In fact, I’ll use them in a similar way as your idea of adding the first and last paragraph to a result’s name seems is very nice. But it’s definitely not nice to do that manually.

First off, what you want can be done with AppleScript, I think. There are two commands that could do it, which one is the right depends on your setup.

DEVONthink can compare via

  • See Also inspector, which takes all available data into account and compares a record to all databases.

  • AppleScript command compare record, which compares records in a similar way as it is done in the See Also inspector. But it does not compare a record to all databases.

  • AppleScript command compare content, which can be used to compare to all databases, but it “only” compares text content.

I’m perfectly fine with the latter as for me it’s more important to compare to all databases.

See this diff, on the left See Also results, on the right compare content results

Back to

and

If it’s not important for you to share exactly the results of the See Also inspector then you could do everything with the script below, it

  • compares text content to all databases
  • sorts by score
  • cuts the results count at the value you set
  • optionally fetches first and last paragraph
  • writes the result names in a markdown record

From your captures it seems that you’re mainly using markdown which should work fine. I did however not had the time to longer test it with PDFs. From short tests it seems it doesn’t make much sense to “blindly” fetch PDF paragraphs. So I suggest, if you test it, to set property maxCharacterCount so low that it won’t exclude e.g. your markdown records but most PDFs. Links to them are always created, only their paragraphs would in the output markdown be replaced by a placeholder. Anyway there are comments.

Before I write on and on, let’s do it the other way round. Give it a try and afterwards I’ll tell you some things that possibly should be considered if you want to use it

-- Create Markdown See Also Suggestion List 

use AppleScript version "2.4"
use framework "Foundation"
use scripting additions

property maxSeeAlsoResults : 20
property removeSuffix : true -- remove suffix of suggested records
property includeParagraphs : true -- fetch the "first" and "last" paragraph. which paragraphs should act as "first" and "last" can be set below 
property skipMarkdownHeading : true -- skip the first non-blank line if it begins with # (independent of property firstParagraphOffset)

property firstParagraphOffset : 1 -- index of the paragraph which should act as the first. starting at 1. only lines which contain at least one word are counted in (independent of property addEmptyLines)
property lastParagraphOffset : 1 -- index of the paragraph which should act as the last. starting at 1. second last would be 2 (and so on)
property theParagraphPlaceholder : "<span style=\"color: red\">Here's something to do!</span>" -- this is used if a paragraph couldn't be fetched, e.g. when property firstParagraphOffset > count of paragraphs. change to your liking
property maxCharacterCount : 100000 -- skip fetching paragraphs of records whose character count is higher. for skipped paragraphs the placeholder is used. add these paragraphs manually afterwards by clicking the suggestion's name

property theOutputGroupUUID : "73964EA3-146B-4CA0-8C6A-456F21CD2C33" -- paste your output group's item link and remove "x-devonthink-item://"
property removeSelectedRecordSuffix : true -- remove suffix of selected record's name for usage in output record's name and heading
property openOutputRecord : true -- only available if one record is selected
property excludeFromSeeAlso : true -- exclude output record from see also
property excludeFromSearch : false -- exclude output record from search

tell application id "DNtp"
	try
		set theRecords to selection of think window 1
		if theRecords = {} then error "Please select some records"
		set theGroup to (get record with uuid theOutputGroupUUID)
		set theDatabases to databases
		
		show progress indicator "Creating See Also Suggestions List... " steps (count theRecords) as string with cancel button
		
		repeat with thisRecord in theRecords
			set thisRecordName to name of thisRecord
			step progress indicator thisRecordName
			set theContent to plain text of thisRecord
			set theSeeAlsoResults_record to {}
			
			repeat with thisDatabase in theDatabases
				set theSeeAlsoResults to compare content theContent to thisDatabase
				repeat with thisResult in theSeeAlsoResults
					set theName to name of thisResult as string
					if removeSuffix = true then set theName to my recordName(theName, filename of thisResult)
					set theName to ("[" & theName & "](" & (reference URL of thisResult) & ")") as string
					if includeParagraphs = true then
						set theCharacterCount to (character count of thisResult)
						if theCharacterCount > 0 and theCharacterCount ≤ maxCharacterCount then
							set end of theSeeAlsoResults_record to {name_:theName, score_:(score of thisResult), charactercount_:theCharacterCount, text_:(plain text of thisResult)}
						else
							set end of theSeeAlsoResults_record to {name_:theName, score_:(score of thisResult), charactercount_:theCharacterCount}
						end if
					else
						set end of theSeeAlsoResults_record to {name_:theName, score_:(score of thisResult), charactercount_:0}
					end if
				end repeat
			end repeat
			
			set theSeeAlsoResults_record_sorted to my sort(theSeeAlsoResults_record)
			if (count theSeeAlsoResults_record_sorted) > maxSeeAlsoResults then set theSeeAlsoResults_record_sorted to (items 1 thru maxSeeAlsoResults in theSeeAlsoResults_record_sorted)
			set theMarkdownText_list to {"<style> a {text-decoration: none;} </style>" & linefeed}
			
			repeat with thisResult in theSeeAlsoResults_record_sorted
				if includeParagraphs = true then
					set theCharacterCount to charactercount_ of thisResult
					if theCharacterCount > 0 and theCharacterCount ≤ maxCharacterCount then
						set theText to text_ of thisResult
						set theParagraphs to paragraphs of theText
						set theParagraphs_cleaned to {}
						repeat with thisParagraph in theParagraphs
							if words in thisParagraph as string > 0 then set end of theParagraphs_cleaned to thisParagraph as string
						end repeat
						if skipMarkdownHeading = true and (item 1 of theParagraphs_cleaned starts with "#") then set theParagraphs_cleaned to (items 2 thru -1 in theParagraphs_cleaned)
						try
							set firstParagraph to item firstParagraphOffset of theParagraphs_cleaned
						on error
							set firstParagraph to theParagraphPlaceholder
						end try
						try
							set lastParagraph to item -lastParagraphOffset of theParagraphs_cleaned
						on error
							set lastParagraph to theParagraphPlaceholder
						end try
						set end of theMarkdownText_list to "* " & name_ of thisResult & space & space & linefeed & firstParagraph & space & space & linefeed & lastParagraph & space & space & linefeed
					else if theCharacterCount > 0 and theCharacterCount > maxCharacterCount then
						set end of theMarkdownText_list to "* " & name_ of thisResult & space & space & linefeed & theParagraphPlaceholder & space & space & linefeed & theParagraphPlaceholder & space & space & linefeed
					end if
				else
					set end of theMarkdownText_list to "* " & name_ of thisResult & space & space & linefeed
				end if
			end repeat
			
			set theMarkdownText to my tid(theMarkdownText_list, linefeed)
			if removeSelectedRecordSuffix = true then set thisRecordName to my recordName(thisRecordName, filename of thisRecord)
			set theSeeAlsoListRecord to create record with {name:"See Also Suggestion List - " & "\"" & thisRecordName & "\"", type:markdown, plain text:("### See Also Suggestion List " & "[" & thisRecordName & "](" & (reference URL of thisRecord) as string) & ")" & linefeed & linefeed & theMarkdownText, exclude from see also:excludeFromSeeAlso, exclude from search:excludeFromSearch} in theGroup
			
		end repeat
		hide progress indicator
		
		if openOutputRecord = true and (count theRecords) = 1 then
			open window for record theSeeAlsoListRecord
			activate
		end if
		
	on error error_message number error_number
		hide progress indicator
		activate
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
		return
	end try
end tell

on recordName(theName, theFilename)
	set theSuffix to my getSuffix(theFilename)
	if theName ends with theSuffix and theName ≠ theSuffix then set theName to characters 1 thru -((length of theSuffix) + 2) in theName as string
	return theName
end recordName

on getSuffix(thePath)
	set revPath to reverse of characters in thePath as string
	set theSuffix to reverse of characters 1 thru ((offset of "." in revPath) - 1) in revPath as string
end getSuffix

on sort(theList)
	set anArray to current application's NSArray's arrayWithArray:theList
	set theDesc to current application's NSSortDescriptor's sortDescriptorWithKey:"score_" ascending:false selector:"compare:"
	set newList to (anArray's sortedArrayUsingDescriptors:{theDesc}) as list
end sort

on tid(theList, theDelimiter)
	set d to AppleScript's text item delimiters
	set AppleScript's text item delimiters to theDelimiter
	set theString to theList as text
	set AppleScript's text item delimiters to d
	return theString
end tid