Find which attributes are populated for a note

How would I go about writing an action code that will give me a list of every attribute that has a non-default value for a given note? Let’s say we put the result in the $Text of a note.

I tried to write an action code that lists attributes with different default values.
I hope it matches what you want to do.

function fGetAttributeList(){
	var:list vKeys;
	var:string vOutput;
	var:string vLeft;
	var:string vRight;
	$Text =;
	
	vKeys = $MySet("System Attributes");
	vKeys.each(aKey){
		vLeft = eval("$"+aKey);
		vLeft = vLeft.replace("\n","");
		vRight = attribute(aKey)["default"];
		vRight = vRight.replace("\n","");
		if(vLeft != vRight){
//			vOutput += aKey + ":" + eval("$"+aKey) +"⬅️" + attribute(aKey)["default"] + "\n";
			vOutput += aKey + "\n";
		};
	};
	
	$Text = "-----System Attribute\n";
	$Text += vOutput;
	vOutput="";
	vKeys = document["user-attributes"];

	vKeys.each(aKey){
		vLeft = eval("$"+aKey);
		vLeft = vLeft.replace("\n","");
		vRight = attribute(aKey)["default"];
		vRight = vRight.replace("\n","");
		if(vLeft != vRight){
//			vOutput += aKey + ":" + eval("$"+aKey) +"⬅️" + attribute(aKey)["default"] + "\n";
			vOutput += aKey + "\n";
		};
	};
	$Text += "\n-----User Attribute\n";
	$Text += vOutput;	
};

(The “replace” function may not be necessary for comparisons.)

AttributeList_without_default_value.tbx (447.4 KB)

3 Likes

Here’s an external script for comparison. It collects attributes of the selected note whose values are not default and places their names and values on the clipboard for pasting wherever.

tell front document of application "Tinderbox 9"
	set outputStr to ""
	repeat with anAttribute in attributes of selected note
		tell anAttribute to if value is not defaultValue then set outputStr to outputStr & name & ": " & value & return
	end repeat
end tell
set the clipboard to outputStr
return outputStr -- line optional, to view in result panel
5 Likes

This is GREAT. Really clean. Lots of ways to modify it. Thanks.

I am happy to be of assistance.

1 Like

If you want to find which (system) attributes in a document use non default values as per the currently open version of Tinderbox:

tell front document of application "Tinderbox 9"
	set outputStr to ""
	repeat with anAttribute in attributes
		tell anAttribute to if value is not defaultValue then set outputStr to outputStr & category & ": $" & name & ": " & value & return
	end repeat
end tell
set the clipboard to outputStr
return outputStr -- line optional, to view in result panel

Notice in the repeat line the ‘selected note’ address is dropped (from the exam[le further above) so we are now reading the doc level values/defaults. I’ve also pre-pended the attribute’s category (Tinderbox attribute group) and a ‘$’ so you get output like:

Events: $TimelineScaleColor2: #f2f2ed
General: $ChildCount: 12
General: $Created: 2010-01-12T09:23:07Z
General: $DescendantCount: 108
General: $DisplayName: Starter_8-5
General: $ID: 1697187039
General: $IDString: tbx:BlKQTf
General: $InboundLinkCount: 1
General: $Modified: 2012-02-15T17:04:00Z
General: $Name: Starter_8-5
General: $Path: /
General: $SelectionCount: 17
General: $SiblingOrder: 1
HTML: $HTMLExportPath: /.html
Net: $NoteURL: tinderbox://?view=outline+select=1697187039
TextFormat: $TextAlign: left
Textual: $EstimatedNoteSize: 11

But why values like a $ChildCount of 11? This is because the attribute is calculated … and the root of the outline has 11 items!. Still, this does show that $TimelineScaleColor2 and $TextAlign have non-default values. BTW, the $Created/Modified dates as those of the outline root level item (not seen in the app) in the XML. This doc was made via the old ‘favourites’ method, i.e. a copy open then saved. I do wonder if doing an explicit ‘Save As’ (Cmd+Opt+Shift+S) might be a better option today.

Sadly, the AppleScript method doesn’t expose whether an attribute is read-only, so we can’t filter those out while scripting without manually making a look-up list of attributes to ignore.

Staying in Tinderbox, currently there is no means to read system attribute names via action code. The document() operator only lists user attributes. But if we had a list of all attributes, attribute() can interrogate any attribute as long as it knows the names. Sadly, attribute() doesn’t reveal is an attribute is read-only. This does make sense as the operator(), as at present, was envisaged primarily for use with user attributes or system ones that are editable.

This AppleScript will list all attributes in the document (filter for category not being ‘user’ to leave out user attributes):

tell front document of application "Tinderbox 9"
	set outputStr to ""
	repeat with anAttribute in attributes
		tell anAttribute to set outputStr to outputStr & name & return
	end repeat
end tell
set the clipboard to outputStr

Helpfully the attributes list A-Z by group and A-Z within group, i.e. the list starts with the ‘AI’ system group, with `DominantLanguage’ being the first item in that group. If you want to remove calculated attributes from the overall list, luckily aTbRef a list of such attributes here.

So non-quite a one click solution but was can do much of it with the various scripts offered in this thread.

4 Likes

On the theory that when it comes to AppleScript with its “flexible” documentation there can never be too many working examples to study, here are some more building on ideas raised by @mwra .

  1. This one will retrieve attributes not in an exclude list:
property excludeAttribs : {"AdornmentCount", "Aliases", "ChildCount", "Created", "Creator", "DescendantCount", "DisplayName", "EstimatedNoteSize", "ID", "IDString", "ImageCount", "InboundLinkCount", "IsAdornment", "IsAgent", "IsAlias", "LastFetched", "LocalAttributes", "Modified", "OutboundLinkCount", "OutlineDepth", "OutlineOrder", "Path", "PlainLinkCount", "ReadCount", "SelectionCount", "SiblingOrder", "TextLength", "TextLinkCount", "WebLinkCount", "WordCount"}

tell front document of application "Tinderbox 9"
	set outputStr to ""
	repeat with anAttribute in attributes
		tell anAttribute to if value is not defaultValue and name is not in excludeAttribs then set outputStr to outputStr & category & ": $" & name & ": " & value & return
	end repeat
end tell
set the clipboard to outputStr
return outputStr -- line optional, to view in result panel

Just set up an exclude list and add is not in to the conditional.

But that script, like the scripts above, is slow.

For much faster results, at the expense of somewhat harder to understand code, take advantage of how efficiently Tinderbox can place values into AppleScript list(s). Then iterate through the AppleScript lists instead retrieving them one by one from Tinderbox.

  1. This one uses that approach get the names of all the attributes in the front document:
-- populate an AppleScript List with attribute names
tell front document of application "Tinderbox 9" to set attrNames to name of attributes

-- convert the AppleScript List to a string
set text item delimiters to return
set the clipboard to attrNames as string

return attrNames as string -- line optional, to view in result pane

  1. And to list category, attribute name, value, and default value (type is also accessible) of attributes not in an exclude list:
property excludeAttribs : {"AdornmentCount", "Aliases", "ChildCount", "Created", "Creator", "DescendantCount", "DisplayName", "EstimatedNoteSize", "ID", "IDString", "ImageCount", "InboundLinkCount", "IsAdornment", "IsAgent", "IsAlias", "LastFetched", "LocalAttributes", "Modified", "OutboundLinkCount", "OutlineDepth", "OutlineOrder", "Path", "PlainLinkCount", "ReadCount", "SelectionCount", "SiblingOrder", "TextLength", "TextLinkCount", "WebLinkCount", "WordCount"}

-- place properties of attributes into three AppleScript lists
tell front document of application "Tinderbox 9" to tell attributes
	set {attrCategories, attrNames, attrValues, attrDefValues} to {category, name, value, defaultValue}
end tell

-- build output string from the three lists using an index
set outputStr to ""
repeat with i from 1 to length of attrNames
	if item i of attrNames is not in excludeAttribs and item i of attrValues is not item i of attrDefValues then
		set outputStr to outputStr & item i of attrCategories & " : " & item i of attrNames & " : " & item i of attrValues & " : " & item i of attrDefValues & return
	end if
end repeat

set the clipboard to outputStr
return outputStr -- line optional, to review in result panel

Note that local attributes and user attributes are in the AppleScript dictionary for Tinderbox 9.

  1. So to get a list of the names of all user attributes in the document:
tell front document of application "Tinderbox 9" to set attrNames to name of user attributes

-- convert the AppleScript List to a string
set text item delimiters to return
set the clipboard to attrNames as string

return attrNames as string -- line optional, to view in result pane

I'm hazy on when, if ever, one might want to use `local attributes` in a script, or how to access them from AppleScript. The above script doesn't work if you simply substitute `local attributes` for `user attributes`.
2 Likes

Delving further with AppleScript Debugger, I misspoke before. The AppleScript doc-scope attributes objects actually all/only the (app’s) system attributes. The document’s user attributes are accessed via the document scope user attributes object.

Although local attributes are a note-level object and they only have a meaning when interrogated at note scope. local attributes includes any attribute system or user that has a value that has neither a default nor inherited (non-default) value.

1 Like

Ah yes, note-level so this works to list the local attributes of a selected note:

tell front document of application "Tinderbox 9"
	set outputStr to ""
	repeat with anAttribute in local attributes of selected note
		tell anAttribute to set outputStr to outputStr & name & " : " & its type & " : " & value & return
	end repeat
end tell
set the clipboard to outputStr
return outputStr -- line optional, to view in result panel
1 Like