Is it possible to add a set of sorting conditions to the sort function?

Just to ask a question, how to create a set of conditions with different priorities for the sort function ? For example, firstly sort by tags, and on this basis, sort by creation date? :thinking:

It’s not possible

Experimental script

You could try this experimental script. It lets you sort by two criteria.

Criteria that should work:

  • addition date
  • comment
  • creation date
  • kind
  • label
  • modification date
  • name
  • path
  • rating
  • tags
  • unread

Example:

To sort by rating from high to low and then by name you would have to change the script to this

set primarySort_Properties to rating of children of theGroup
set primarySort_Ascending to false

set secondarySort_Properties to name of children of theGroup
set secondarySort_Ascending to true

Some things to keep in mind:

  • You have to test whether a sort criterion needs ascending or descending order.
  • The sorted results are shown in a new window. Close this before you run the script again.
  • You can “save” the sorted order if you replicate or duplicate the results to a new group and sort this group by “Unsorted”. Do not move results out of the results window, if you do you’ll lose all replicants.

That’s it.

-- Experimental script

-- Set your primary sort criteria and its sort order
-- Set your secondary sort criteria and its sort order
-- Select one group in the sidebar

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

tell application id "DNtp"
	try
		if exists (root of viewer window 1) then
			set theGroup to (root of viewer window 1)
		else
			error "Please select one group in the sidebar"
		end if
		
		------------------------------------------------------------------------------
		------------------------------------------------------------------------------
		
		-- Set your primary and secondary sort criteria here
		-- e.g. addition date, comment, creation date, kind, label, modification date, name, path, rating, tags, unread 
		
		set primarySort_Properties to label of children of theGroup
		set primarySort_Ascending to true
		
		set secondarySort_Properties to name of children of theGroup
		set secondarySort_Ascending to true
		
		------------------------------------------------------------------------------
		------------------------------------------------------------------------------
		
		set theUUIDs to uuid of children of theGroup
		
		set theClass_1 to class of (item 1 of primarySort_Properties)
		set theClass_2 to class of (item 1 of secondarySort_Properties)
		
		set theProperties_record to {}
		
		repeat with i from 1 to (count theUUIDs)
			set thisProperty_1 to (item i of primarySort_Properties)
			if theClass_1 = list then set thisProperty_1 to my tid(my sort_list(thisProperty_1), ",")
			set thisProperty_2 to (item i of secondarySort_Properties)
			if theClass_2 = list then set thisProperty_2 to my tid(my sort_list(thisProperty_2), ",")
			set end of theProperties_record to {property_1:thisProperty_1, property_2:thisProperty_2, uuid_:(item i of theUUIDs)}
		end repeat
		
		set theProperties_record_sorted to my sortByProperty1AndProperty2(theProperties_record)
		
		set theSortedChildren to {}
		
		repeat with this_record in theProperties_record_sorted
			set thisChild to (get record with uuid (uuid_ of this_record))
			set end of theSortedChildren to thisChild
		end repeat
		
		set newWindow to open window for record (root of current database)
		set search results of newWindow to theSortedChildren
		activate
		
	on error error_message number error_number
		using terms from scripting additions
			if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
		end using terms from
		return
	end try
end tell

on sortByProperty1AndProperty2(theList)
	set theArray to current application's NSArray's arrayWithArray:theList
	set theSelector_1 to "localizedCompare:"
	if my theClass_1 is not in {text, list} then set theSelector_1 to "compare:"
	set theDescriptor_1 to current application's NSSortDescriptor's sortDescriptorWithKey:"property_1" ascending:(my primarySort_Ascending) selector:theSelector_1
	set theSelector_2 to "localizedCompare:"
	if my theClass_2 is not in {text, list} then set theSelector_2 to "compare:"
	set theDescriptor_2 to current application's NSSortDescriptor's sortDescriptorWithKey:"property_2" ascending:(my secondarySort_Ascending) selector:theSelector_2
	set newList to (theArray's sortedArrayUsingDescriptors:{theDescriptor_1, theDescriptor_2}) as list
end sortByProperty1AndProperty2

on sort_list(theList)
	considering numeric strings
		set theIndexList to {}
		set theSortedList to {}
		repeat (length of theList) times
			set theLowItem to ""
			repeat with a from 1 to (length of theList)
				if a is not in theIndexList then
					set theCurrentItem to item a of theList as text
					if theLowItem is "" then
						set theLowItem to theCurrentItem
						set theLowItemIndex to a
					else if theCurrentItem comes before theLowItem then
						set theLowItem to theCurrentItem
						set theLowItemIndex to a
					end if
				end if
			end repeat
			set end of theSortedList to theLowItem
			set end of theIndexList to theLowItemIndex
		end repeat
	end considering
	return theSortedList
end sort_list

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

set theGroup to (root of viewer window 1) as list of real or real

This is an invalid statement and the script doesn’t compile.

Huh? Exactly this script ran successfully from within Script Debugger and from DEVONthink’s script menu.

This statement makes sure that only one group is selected, it has been in the script since the beginning.

Thanks for letting me know, I’ll check this again later.

This statement makes sure that only one group is selected

Why don’t you just check if the root exists? :thinking:

tell application id "DNtp"
	if exists (root of viewer window 1) then
      -- Do stuff
    end if
end tell

Ok, checked. Script from above runs fine over here.

Good question …

I have some DEVONthink AppleScript issues / feature requests that don’t deserve a thread, so here goes:

DEVONthink’s AppleScript dictionary is really great but it got some annoying issues when it comes to making new windows.

  • Bounds can only be set after a window is opened. This often results in an annoying “jump” of the new window. open window for would be so much nicer if it could be extended with properties {bounds:{560, 296, 2000, 1142}}.

  • New windows sometimes show the sidebar / the preview / the inspector - and sometimes not. Would be great if there were properties to set show/hidden status of each. Would be superb to have properties to show/hide the different sections of navigation sidebar. And properties for each inspector tab would be nice too.

  • It’s not possible to reliably open a new window. open window for record doesn’t open an additional window if there’s already one for e.g. root of inbox. If open window for record didn’t open a new window and is followed by setting the search results then the windows selection is lost. It should at least be possible to open a new window for each database’s root.

Hmm.

If it still doesn’t work for you try restarting your mac. If this doesn’t help please start a support ticket. :wink:

  • Bounds can only be set after a window is opened. This often results in an annoying “jump” of the new window. open window for would be so much nicer if it could be extended with properties {bounds:{560, 296, 2000, 1142}} .

This is true of any application I’ve ever scripted, not just a DEVONthink behavior.

Would be great if there were properties to set show/hidden status of each. Would be superb to have properties to show/hide the different sections of navigation sidebar. And properties for each inspector tab would be nice too.

The requests are noted, with no promises.


Have you tried compiliing and running in Script Editor?
If not, do so.
And a note: you shouldn’t assume people are running Script Debugger, nor should it be a prerequisite for scripting.

Oh my goodness!!! thank you so much :rose: Let me have a try~

Did it now. It compiles and runs from Script Editor. Saving in Script Editor and using it from DEVONthink works too.

To make sure Script Debugger didn’t do anything in the background I even restarted my mac, copied the above script, compiled and saved in Script Editor again. It’s all fine.

Do you have scripting additions installed? Does Script Editor report anything when it refuses to compile?

@Fu.nyanderful Does the script compile and run in Script Editor.app?

Sorry to reply to you after a week! For some personal reasons :eyes:
Emmm, I think my google translation may not be very useful, so I have spent a little time figuring out what you are discussing… :stuck_out_tongue:

Yes, and I also encountered the same problem as @BLUEFROG that the script cannot be saved

I don’t know if I should replace the wrong part with this part?

I think I found out what happened. Please try the updated script from my first post. Note: You have to set your sort criteria.

I first couldn’t believe this as everything’s working fine over here.

But instead of asking if and what scripting additions you have installed I should have checked what I have installed …

When I wrote as anything in Script Debugger it automatically changed to as list of real or real.

Last week a startpage.com search for “as list of real or real” returned 0 results, this week this thread is the only result.

Obvious that this is no common AppleScript statement …

Today I searched again, this time with Google which also returned a MacScripter thread with this:

If you include ‘use scripting additions’, the coercion changes to ‘as list of real or real’!

Later in the thread someone found that

it looks like that only happens with Satimage.osax installed

So I temporarily removed Satimage.osax, restarted Script Debugger and compiled again.

This time as anything was changed to as list of string or string (!!!)

Turned out that this time XMLLib.osax was responsible …

I think I know understand why we should avoid dependencies wherever possible. :sweat_smile:

I’ve updated the script in my first post, does it compile in Script Editor?

success~! all the best!! :tada:

Great! :slight_smile:

But there’s still one thing I’m not sure about …

@cgrunenberg, does children of always return children in the same order?

So would e.g. these two lines always return results in the same order?

set X to label of children of theGroup		
set Y to name of children of theGroup

If not, would it make a difference if I assign variables like so:

set {X, Y} to {label, name} of children of theGroup

The returned order should be identical to Unsorted sorting.

1 Like