Tinderbox Forum

AppleScript: Batch creating user attributes


(Peter Punk) #1

Hi there! Yesterday I wanted to paste a CSV from Numbers, so I first copied the column names in order to create user attributes, cause I learned here that Tinderbox will then match the pasted CSV to those attributes which is very nice.

I then realized I was too lazy to do this all manually and launched UI Browser which is also very nice. However several hours later I’ve got an AppleScript, which seems to be the answer - or at least a good starting point - to the unsolved question of creating (not transfering yet…) user attributes for those of use who use more than one Tinderbox.

This script batch creates user attributes. It handles names separated by comma, tab or new line. If names have characters which aren’t allowed in attribute names it will replace those with underscores, so I never have to think of this again (if I have not forgotten some…).

In the “property” section you can set the options known from Document Inspector’s “User” tab, but not on single attribute level; for each run those options will be assigned to all attributes, meaning that the only difference between attributes created in one run is their name.

Run from Script Editor it should be easy to change options between runs (but there are also other ways to use it, more on this later). After a run you can change options of single attributes of course one by one, but probably it makes more sense to do more runs with different options than changing options manually afterwards.

Tinderbox Inspector must be open as UI scripting is used (and possibly you have to allow UI scripting in macOS, but I’m not sure if this is still necessary).

By changing defaultAnswer you can change what is presented in the dialog that asks for the attribute names:

  • With “the clipboard” (without quotes) you’ll get… e.g. the column names you just copied in Numbers.

  • With “” you’ll just get an empty text field. If you use this I recommend using commas or tabs, as for new lines you’ll have to hit option + return.

But what if you know there are those attributes you’ve created over and over again in every new Tinderbox and you’re just tired of typing (ok, pasting) those again and again? (Yes, I know stationaries…)

  • In this case I’ll bet your choice will be the AppleScript list. Just store your attributes names like this {“A”,“B”,“D”} and you’ll never need to create those manually again!

Sounds nice so far?

Ok.

Now imagine what storing different versions of this script with different AppleScript lists and/or different options could do.

Got it? :smirk:

If you have a script version for every frequently used set of user attributes, then it’s just:

  • Open in Script Editor,
  • run,
  • wait,
  • close.

That’s it.

And if you make an AppleScript app you don’t even need to open Script Editor for this.

One click. There is your set of user attributes. Across Tinderboxes. :sunglasses:

Didn’t really tested yet, only while writing, but it’s seems to be very smooth and with a lot of potential

Perhaps that’s the “missing link” between blank Tinderboxes and stationaries? :slight_smile: What do you think?

			-- Handler from http://applescript.bratis-lover.net

			-- This script batch creates user attributes. It handles names separated by comma, tab or new line. (In the first place I started writing this as I was looking for an easier way to create attributes before pasting CSV from Numbers.app). If the names have characters which aren't allowed in attribute names it will replace those with underscores. 
			-- In the "property" section you can set the options known from Document Inspector's "User" tab, but not on single attribute level; for each run those options will be assigned to all attributes.
			-- Run from Script Editor it should be easy to change options between runs. After a run you can change options of single attributes of course one by one, but probably it makes more sense to do more runs with different options than changing options manually afterwards.

			-- Tinderbox Inspector must be open as UI scripting is used (and possibly you have to allow UI scripting in macOS, not sure.)

			-- You can change what is shown in the dialog that asks for the attribute nanes (defaultAnswer):
			-- With "the clipboard" (without quotes) you'll get.. e.g. the column names you just copied in Numbers.
			-- With "" you'll just get an empty text field. If you use this I recommend using commas or tabs, as for new lines you'll have to hit option + return.
			-- But what if you know there are those attributes you've created over and over again in every new Tinderbox (as long as you don't use stationaries, which, well, are stationary..) and you're tired of typing those again and again? In this case I'll bet your choice will be an AppleScript list. Just store your attributes names like this {"A","B","D"} and you'll never need to create those manually again.

			property _Type : "s" -- s[tring], c[olor], n[umber], f[ile], b[oolean], d[ate], se[t], u[rl], l[ist], i[nterval]
			property _Default : ""
			property _Suggested : "" -- "Ant;Bee;Cow" (Quotes only in AppleScript, see http://www.acrobatfaq.com/atbref7/index/MiscUserInterfaceAspects/Pre-populatingkeyattribu.html)
			property _Sequential : false -- (didn't test this)
			property _KeyAttribute : false
			property _Description : ""

			property replaceChars : {" ", "-", ",", ";", "?", ".", "(", ")", "[", "]", "*", "/", "&", "$"} -- characters doesn't allowed in attribute names (complete?)
			property theDelay : 0.2 -- change if needed

			set defaultAnswer to the clipboard -- the clipboard, "" (blank text field), or an AppleScript List {"A","B","C"}
			#set defaultAnswer to "" -- the clipboard, "" (blank text field), or an AppleScript List {"A","B","C"}
			#set defaultAnswer to "Id	Projekt	Reporter	Priorität	Schweregrad	Reproduzierbar	Produktversion	Meldungsdatum	Betriebssystem	BS-Version	Rechnertyp	Sichtbarkeit	Aktualisiert	Zusammenfassung	Status	Lösung	Behoben in Version" -- the clipboard, "" (blank text field), or an AppleScript List {"A","B","C"}

			tell application "SystemUIServer"
				activate
				set _Names to text returned of (display dialog "Attribute names (separated by comma, tab or new line):" default answer defaultAnswer default button 2) as string
				if _Names is "" then return
			end tell

			if _Names contains "," then
				set _Names to replaceString(_Names, ",", return)
			end if

			if _Names contains tab then
				set _Names to my replaceString(_Names, tab, return)
			end if

			if _Names ends with return or _Names ends with character id 10 then
				set _Names to my trimBoth(_Names)
			end if

			set _Names to paragraphs of _Names

			if _Names = {} then return

			activate application "Tinderbox 7"
			tell application "System Events"
				try
					tell process "Tinderbox"
						try
							set theWindow to (first window whose value of attribute "AXRoleDescription" is "floating window")
							if name of theWindow does not start with "Document Inspector:" then
								click radio button 2 of radio group 1 of theWindow
								set theWindow to (first window whose value of attribute "AXRoleDescription" is "floating window")
								click radio button 2 of tab group 1 of theWindow
							end if
						on error
							display dialog "Please open the Inspector window"
							return
						end try
						
						repeat with thisName in _Names
							
							click menu button 1 of tab group 1 of theWindow
							click menu item 2 of menu 1 of menu button 1 of tab group 1 of theWindow
							
							repeat with thisChar in replaceChars
								if thisName contains thisChar then
									set thisName to my replaceString(thisName, thisChar, "_")
								end if
							end repeat
							
							set focused of text field 2 of tab group 1 of theWindow to true -- Name
							set value of text field 2 of tab group 1 of theWindow to thisName
							key code 36
							delay theDelay
							
							if _Type is not "s" then -- Type
								click pop up button 2 of tab group 1 of theWindow
								keystroke _Type
								key code 36
								delay theDelay
							end if
							
							if _Default is not "" then -- Default
								set focused of text field 1 of tab group 1 of theWindow to true
								set value of text field 1 of tab group 1 of theWindow to _Default
								key code 36
								delay theDelay
							end if
							
							if _Suggested is not "" then -- Suggested
								set focused of text field 4 of tab group 1 of theWindow to true
								set value of text field 4 of tab group 1 of theWindow to _Suggested
								key code 36
								delay theDelay
							end if
							
							if _Sequential is not false then -- sequential
								if value of checkbox 2 of tab group 1 of theWindow is not 1 then
									click checkbox 2 of tab group 1 of theWindow
								end if
							end if
							
							if _KeyAttribute is not false then -- Key attribute
								if value of checkbox 1 of tab group 1 of theWindow is not 1 then
									click checkbox 1 of tab group 1 of theWindow
								end if
							end if
							
							if _Description is not "" then -- Description
								set focused of text field 3 of tab group 1 of theWindow to true
								set value of text field 3 of tab group 1 of theWindow to _Description
								key code 36
								delay theDelay
							end if
							
						end repeat
						
						set theCount to count of _Names
						display dialog "If successful there should be " & theCount & " new attributes. Please check!"
						
					end tell
					
				on error error_message number error_number
					set the clipboard to error_number as string
					display notification "Copied Error Number to clipboard" with title error_number
				end try
			end tell

			on replaceString(theText, oldString, newString)
				local ASTID, theText, oldString, newString, lst
				set ASTID to AppleScript's text item delimiters
				try
					considering case
						set AppleScript's text item delimiters to oldString
						set lst to every text item of theText
						set AppleScript's text item delimiters to newString
						set theText to lst as string
					end considering
					set AppleScript's text item delimiters to ASTID
					return theText
				on error eMsg number eNum
					set AppleScript's text item delimiters to ASTID
					error "Can't replaceString: " & eMsg number eNum
				end try
			end replaceString

			on trimStart(str)
				local str, whiteSpace
				try
					set str to str as string
					set whiteSpace to {character id 10, return, space, tab}
					try
						repeat while str's first character is in whiteSpace
							set str to str's text 2 thru -1
						end repeat
						return str
					on error number -1728
						return ""
					end try
				on error eMsg number eNum
					error "Can't trimStart: " & eMsg number eNum
				end try
			end trimStart

			on trimEnd(str)
				local str, whiteSpace
				try
					set str to str as string
					set whiteSpace to {character id 10, return, space, tab}
					try
						repeat while str's last character is in whiteSpace
							set str to str's text 1 thru -2
						end repeat
						return str
					on error number -1728
						return ""
					end try
				on error eMsg number eNum
					error "Can't trimEnd: " & eMsg number eNum
				end try
			end trimEnd


			on trimBoth(str)
				local str
				try
					return my trimStart(my trimEnd(str))
				on error eMsg number eNum
					error "Can't trimBoth: " & eMsg number eNum
				end try
			end trimBoth

(Paul Walters) #2

This is a very clever idea – I haven’t tried it yet but will test it.

A few notes for anyone not familiar with AppleScript or user interface scripting (UI scripting).

  1. UI scripting can damage a document if not done precisely – this sort of scripting will just “blindly” do what it does and takes somewhat of a bull-in-a-china shop approach. That’s not to say it’s bad, or a criticism of @ian’s contribution. Just beware. Always use a UI script on a new document or a document that you have made a backup copy of immediately before running the script.
  2. The script depends on the version of Tinderbox that existed when the script was written. Things can change in the Inspector and elsewhere, and so letting the script lose on a new version of Tinderbox should be done carefully – see #1, above. (This does happen: in the old forum there are scripts posted that will not work. Things get abandoned.)
  3. The Eastgate-provided, and well seasoned approach to creating documents that encompass a set of user attributes you want to use frequently is to create a document with those attributes and save that document to
~/Library/Application Support/Tinderbox/favorites

And then, use File > Open Favorites to access your favorite documents and have Tinderbox create a new document based on one of your favorite starting points.


(Mark Anderson) #3

Interesting idea and thanks for sharing.

Most Tinderbox customisation extensions (badges, colours, etc.) use XML-based data and IIRC there is/was a feature request to let the user store a set of pre-configured user attributes so as to be used by all the user’s new TBXs.

Another easy way to generate attributes en masse is to use the Tab-delim/CSV table import - see here and here.

Another successful TBX pre-customisation route is to store a customised but otherwise blank TBX in the ‘favorites’ app support folder and set in Finder as a stationery file, as mentioned in @PaulWalters’ post above. To expand a little on the latter approach, the result is that when you open said file from the File -> Favorites sub menu an unsaved copy of the original file is opened. Thus a freshly minted, customised file each time. An advantage for those taking this tack is you can do lots of other customisations too - stamps, colours, export templates, prototypes, composites, custom doc-level defaults for system attributes, etc.Effectively you’re making a custom configuration file in the form of a TBX.


(Mark Anderson) #5

I’ve edited my last post above to clarify that I’m expanding the explanation of the technique previously mentioned by @PaulWalters. I added the explanation as stationery files are less talked about of late and thus often a surprise to newer Mac users.