Script help: convert TP2 script to TP3

Hi all,

“Long” time ago I’ve written a Applescript for TP2 in order to add a auto numbered tag to a line.

This script adds an issue Tag to the selected entry. The value of the Tag will automatic increment based on the latest numbered issue. Because the items are ordered by priority (not by ‘issue’ number) I check the complete document. The script runs via Keyboard Maestro.

A document looks like:

Project item 1:
-  this is an issue @issue(123)
-  this is an other issue @issue(32)

Project 2
-  this is an issue @issue(12) @now
-  this is an other NEW issue <= here has to come number @issue(124)   

Because the manual for scripting is not completed yet, I’am not able to translate this script for TP3. So I hope someone here can help me!

My script for TP2 is:

-- set the name for the tag
property tagName : "issue"
property latest_issue : 1

tell application "TaskPaper"
	tell front document
		set current_entry to «class STsy»
		set selected_entries to get every «class TPer»
		repeat with each in selected_entries
			if (exists «class TPtg» named tagName of each) then
				set this_issue to («class TGvl» of «class TPtg» named tagName) in each as number
				if (this_issue is greater than latest_issue) then
					set latest_issue to this_issue
				end if
			end if
		end repeat
		if (not (exists «class TPtg» named tagName in current_entry)) then
			tell current_entry
				make «class TPtg» with properties {name:tagName, «class TGvl»:(latest_issue + 1)}
			end tell
		end if
	end tell
end tell


Perhaps something like the script below ?

In Keyboard Maestro you could paste the code into an Execute JavaScript for Automation action.

(You should be able to find descriptions of the properties and methods in, and more general material on scripts in and these threads:

(function () {
    'use strict';

    function fn(editor, options) {
        var outline = editor.outline,
            sln = editor.selection.startItem,
            strTag = options.tagName,
            strAttr = 'data-' + strTag;

        if (sln && !sln.hasAttribute(strAttr)) {

                function () {
                        strAttr, outline
                        // list the items with that tag,
                        .evaluateItemPath('//@' + strTag)

                        // and trawl for their highest value.
                            function (a, x) {
                                var v = x.getAttribute(strAttr),
                                    n = parseInt(v, 10) || 0;

                                return n > a ? n : a;
                            0 // start at zero,
                        ) + 1 // add one to the final max.

    var ds = Application("TaskPaper")
        varResult = ds.length ? ds[0].evaluate({
            script: fn.toString(),
            withOptions: {
                tagName: 'issue'
        }) : false;

    return varResult

Hi @complexpoint

Thnx, your script is already working!! The only thing I mis is the check if a issue tag already exist.In that case the script should not be executed.


@complexpoint is too fast… I was also working on a solution so here’s mine for what its worth :smile:

function TaskPaperContextScript(editor, options) {
  var outline = editor.outline;
  var maxIssue = 0;
  outline.evaluateItemPath('//@issue').forEach(function (each) {
  	issue = each.getAttribute('data-issue', Number)
	if (!isNaN(issue)) {
   	  maxIssue = Math.max(issue, maxIssue);
  outline.groupUndoAndChanges(function() {
    editor.selection.selectedItems.forEach(function (each) {
	  if (!each.hasAttribute('data-issue')) {
	    each.setAttribute('data-issue', ++maxIssue);

  script: TaskPaperContextScript.toString()

Hi Jesse,

You too, really thnx! Works great!


Jesse’s is much better : - )

I posted mine after yours. And I’ve already changed my script about 3 times fixing various bugs.

But this actually brings up a recent API change that can make future scripts a bit simpler. In your script you are checking the result of item.getAttribute() for Number vrs String values. As of a few versions ago this check isn’t needed, all values stored in item Attributes will always be stored as string values. So you always get strings!

If you set an attribute using a non-string value then the value is converted to a string for you before being stored. For some types of objects (Numbers, Dates) TaskPaper also supports reversing that transform for you. To do this you can pass the object class that you want when using item.getAttribute(). See my updated script above.

The reason that this is done is so that scripts won’t get tripped up when an outline is serialized. Serialization always turns all values into strings… so now that’s no longer a special case to be aware of, because those values are always stored as strings anyway.

1 Like

Thanks ! That does make things simpler.